// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/layers/picture_layer_impl.h"

#include <stddef.h>

#include <algorithm>
#include <limits>
#include <set>
#include <utility>

#include "base/location.h"
#include "base/macros.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/animation/animation_host.h"
#include "cc/base/math_util.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/picture_layer.h"
#include "cc/output/buffer_to_texture_target_map.h"
#include "cc/quads/draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/test/begin_frame_args_test.h"
#include "cc/test/fake_compositor_frame_sink.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_layer_tree_host_client.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/fake_raster_source.h"
#include "cc/test/fake_recording_source.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/gpu_rasterization_enabled_settings.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/test_layer_tree_host_base.h"
#include "cc/test/test_task_graph_runner.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "cc/tiles/tiling_set_raster_queue_all.h"
#include "cc/tiles/tiling_set_raster_queue_required.h"
#include "cc/trees/layer_tree_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"

namespace cc {
namespace {

#define EXPECT_BOTH_EQ(expression, x)              \
    do {                                           \
        EXPECT_EQ(x, pending_layer()->expression); \
        EXPECT_EQ(x, active_layer()->expression);  \
    } while (false)

#define EXPECT_BOTH_NE(expression, x)              \
    do {                                           \
        EXPECT_NE(x, pending_layer()->expression); \
        EXPECT_NE(x, active_layer()->expression);  \
    } while (false)

#define EXPECT_BOTH_TRUE(expression)              \
    do {                                          \
        EXPECT_TRUE(pending_layer()->expression); \
        EXPECT_TRUE(active_layer()->expression);  \
    } while (false)

#define EXPECT_BOTH_FALSE(expression)              \
    do {                                           \
        EXPECT_FALSE(pending_layer()->expression); \
        EXPECT_FALSE(active_layer()->expression);  \
    } while (false)

    class MockCanvas : public SkCanvas {
    public:
        explicit MockCanvas(int w, int h)
            : SkCanvas(w, h)
        {
        }

        void onDrawRect(const SkRect& rect, const SkPaint& paint) override
        {
            // Capture calls before SkCanvas quickReject() kicks in.
            rects_.push_back(rect);
        }

        std::vector<SkRect> rects_;
    };

    class PictureLayerImplTest : public TestLayerTreeHostBase {
    public:
        void SetUp() override
        {
            TestLayerTreeHostBase::SetUp();
            host_impl()->SetViewportSize(gfx::Size(10000, 10000));
        }

        LayerTreeSettings CreateSettings() override
        {
            LayerTreeSettings settings;
            settings.gpu_rasterization_enabled = true;
            settings.layer_transforms_should_scale_layer_contents = true;
            settings.create_low_res_tiling = true;
            settings.verify_clip_tree_calculations = true;
            settings.renderer_settings.buffer_to_texture_target_map = DefaultBufferToTextureTargetMapForTesting();
            return settings;
        }

        void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds,
            const gfx::Size& tile_size,
            const Region& invalidation)
        {
            scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
            scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

            SetupTreesWithFixedTileSize(std::move(pending_raster_source),
                std::move(active_raster_source), tile_size,
                invalidation);
        }

        void SetupTreesWithFixedTileSize(
            scoped_refptr<RasterSource> pending_raster_source,
            scoped_refptr<RasterSource> active_raster_source,
            const gfx::Size& tile_size,
            const Region& pending_invalidation)
        {
            SetupPendingTree(std::move(active_raster_source), tile_size, Region());
            ActivateTree();
            SetupPendingTree(std::move(pending_raster_source), tile_size,
                pending_invalidation);
        }

        void SetupDefaultTreesWithInvalidation(const gfx::Size& layer_bounds,
            const Region& invalidation)
        {
            scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
            scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

            SetupTreesWithInvalidation(std::move(pending_raster_source),
                std::move(active_raster_source), invalidation);
        }

        void SetupTreesWithInvalidation(
            scoped_refptr<RasterSource> pending_raster_source,
            scoped_refptr<RasterSource> active_raster_source,
            const Region& pending_invalidation)
        {
            SetupPendingTree(std::move(active_raster_source), gfx::Size(), Region());
            ActivateTree();
            SetupPendingTree(std::move(pending_raster_source), gfx::Size(),
                pending_invalidation);
        }

        void SetupPendingTreeWithInvalidation(
            scoped_refptr<RasterSource> raster_source,
            const Region& invalidation)
        {
            SetupPendingTree(std::move(raster_source), gfx::Size(), invalidation);
        }

        void SetupPendingTreeWithFixedTileSize(
            scoped_refptr<RasterSource> raster_source,
            const gfx::Size& tile_size,
            const Region& invalidation)
        {
            SetupPendingTree(std::move(raster_source), tile_size, invalidation);
        }

        void SetupDrawProperties(FakePictureLayerImpl* layer,
            float ideal_contents_scale,
            float device_scale_factor,
            float page_scale_factor,
            float maximum_animation_contents_scale,
            float starting_animation_contents_scale,
            bool animating_transform_to_screen)
        {
            layer->layer_tree_impl()->SetDeviceScaleFactor(device_scale_factor);
            host_impl()->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);

            gfx::Transform scale_transform;
            scale_transform.Scale(ideal_contents_scale, ideal_contents_scale);
            layer->draw_properties().screen_space_transform = scale_transform;
            layer->set_is_drawn_render_surface_layer_list_member(true);
            DCHECK_EQ(layer->GetIdealContentsScale(), ideal_contents_scale);
            layer->layer_tree_impl()->property_trees()->SetAnimationScalesForTesting(
                layer->transform_tree_index(), maximum_animation_contents_scale,
                starting_animation_contents_scale);
            layer->draw_properties().screen_space_transform_is_animating = animating_transform_to_screen;
        }

        void SetupDrawPropertiesAndUpdateTiles(
            FakePictureLayerImpl* layer,
            float ideal_contents_scale,
            float device_scale_factor,
            float page_scale_factor,
            float maximum_animation_contents_scale,
            float starting_animation_contents_scale,
            bool animating_transform_to_screen)
        {
            SetupDrawProperties(layer, ideal_contents_scale, device_scale_factor,
                page_scale_factor, maximum_animation_contents_scale,
                starting_animation_contents_scale,
                animating_transform_to_screen);
            layer->UpdateTiles();
        }

        static void VerifyAllPrioritizedTilesExistAndHaveRasterSource(
            const PictureLayerTiling* tiling,
            RasterSource* raster_source)
        {
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
            for (PictureLayerTiling::CoverageIterator iter(
                     tiling, tiling->contents_scale(),
                     gfx::Rect(tiling->tiling_size()));
                 iter; ++iter) {
                EXPECT_TRUE(*iter);
                EXPECT_EQ(raster_source, prioritized_tiles[*iter].raster_source());
            }
        }

        void SetContentsScaleOnBothLayers(float contents_scale,
            float device_scale_factor,
            float page_scale_factor,
            float maximum_animation_contents_scale,
            float starting_animation_contents_scale,
            bool animating_transform)
        {
            SetupDrawPropertiesAndUpdateTiles(
                pending_layer(), contents_scale, device_scale_factor, page_scale_factor,
                maximum_animation_contents_scale, starting_animation_contents_scale,
                animating_transform);

            SetupDrawPropertiesAndUpdateTiles(
                active_layer(), contents_scale, device_scale_factor, page_scale_factor,
                maximum_animation_contents_scale, starting_animation_contents_scale,
                animating_transform);
        }

        void ResetTilingsAndRasterScales()
        {
            if (pending_layer()) {
                pending_layer()->ReleaseTileResources();
                EXPECT_FALSE(pending_layer()->tilings());
                pending_layer()->RecreateTileResources();
                EXPECT_EQ(0u, pending_layer()->tilings()->num_tilings());
            }

            if (active_layer()) {
                active_layer()->ReleaseTileResources();
                EXPECT_FALSE(active_layer()->tilings());
                active_layer()->RecreateTileResources();
                EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
            }
        }

        size_t NumberOfTilesRequired(PictureLayerTiling* tiling)
        {
            size_t num_required = 0;
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            for (size_t i = 0; i < tiles.size(); ++i) {
                if (tiles[i]->required_for_activation())
                    num_required++;
            }
            return num_required;
        }

        void AssertAllTilesRequired(PictureLayerTiling* tiling)
        {
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            for (size_t i = 0; i < tiles.size(); ++i)
                EXPECT_TRUE(tiles[i]->required_for_activation()) << "i: " << i;
            EXPECT_GT(tiles.size(), 0u);
        }

        void AssertNoTilesRequired(PictureLayerTiling* tiling)
        {
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            for (size_t i = 0; i < tiles.size(); ++i)
                EXPECT_FALSE(tiles[i]->required_for_activation()) << "i: " << i;
            EXPECT_GT(tiles.size(), 0u);
        }

        void SetInitialDeviceScaleFactor(float device_scale_factor)
        {
            // Device scale factor is a per-tree property. However, tests can't directly
            // set the pending tree's device scale factor before the pending tree is
            // created, and setting it after SetupPendingTree is too late, since
            // draw properties will already have been updated on the tree. To handle
            // this, we initially set only the active tree's device scale factor, and we
            // copy this over to the pending tree inside SetupPendingTree.
            host_impl()->active_tree()->SetDeviceScaleFactor(device_scale_factor);
        }

        void TestQuadsForSolidColor(bool test_for_solid);
    };

    class NoLowResPictureLayerImplTest : public PictureLayerImplTest {
    public:
        LayerTreeSettings CreateSettings() override
        {
            LayerTreeSettings settings = PictureLayerImplTest::CreateSettings();
            settings.create_low_res_tiling = false;
            return settings;
        }
    };

    TEST_F(PictureLayerImplTest, CloneNoInvalidation)
    {
        gfx::Size layer_bounds(400, 400);
        SetupDefaultTrees(layer_bounds);

        EXPECT_EQ(pending_layer()->tilings()->num_tilings(),
            active_layer()->tilings()->num_tilings());

        const PictureLayerTilingSet* tilings = pending_layer()->tilings();
        EXPECT_GT(tilings->num_tilings(), 0u);
        for (size_t i = 0; i < tilings->num_tilings(); ++i)
            EXPECT_TRUE(tilings->tiling_at(i)->AllTilesForTesting().empty());
    }

    TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        gfx::Size layer_bounds(400, 400);
        SetupDefaultTrees(layer_bounds);

        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        // Update tiles with viewport for tile priority as (0, 0, 100, 100) and the
        // identify transform for tile priority.
        gfx::Rect viewport_rect_for_tile_priority = gfx::Rect(0, 0, 100, 100);
        gfx::Transform transform, transform_for_tile_priority;

        host_impl()->SetExternalTilePriorityConstraints(
            viewport_rect_for_tile_priority, transform_for_tile_priority);
        bool update_lcd_text = false;
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);

        gfx::Rect viewport_rect_for_tile_priority_in_view_space = viewport_rect_for_tile_priority;

        // Verify the viewport rect for tile priority is used in picture layer tiling.
        EXPECT_EQ(viewport_rect_for_tile_priority_in_view_space,
            active_layer()->viewport_rect_for_tile_priority_in_content_space());
        PictureLayerTilingSet* tilings = active_layer()->tilings();
        for (size_t i = 0; i < tilings->num_tilings(); i++) {
            PictureLayerTiling* tiling = tilings->tiling_at(i);
            EXPECT_EQ(
                tiling->GetCurrentVisibleRectForTesting(),
                gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
                    tiling->contents_scale()));
        }

        // Update tiles with viewport for tile priority as (200, 200, 100, 100) in
        // screen space and the transform for tile priority is translated and
        // rotated. The actual viewport for tile priority used by PictureLayerImpl
        // should be (200, 200, 100, 100) applied with the said transform.
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100);
        transform_for_tile_priority.Translate(100, 100);
        transform_for_tile_priority.Rotate(45);
        host_impl()->SetExternalTilePriorityConstraints(
            viewport_rect_for_tile_priority, transform_for_tile_priority);
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);

        gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
        bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
        EXPECT_TRUE(success);

        // Note that we don't clip this to the layer bounds, since it is expected that
        // the rect will sometimes be outside of the layer bounds. If we clip to
        // bounds, then tile priorities will end up being incorrect in cases of fully
        // offscreen layer.
        viewport_rect_for_tile_priority_in_view_space = MathUtil::ProjectEnclosingClippedRect(screen_to_view,
            viewport_rect_for_tile_priority);

        EXPECT_EQ(viewport_rect_for_tile_priority_in_view_space,
            active_layer()->viewport_rect_for_tile_priority_in_content_space());
        tilings = active_layer()->tilings();
        for (size_t i = 0; i < tilings->num_tilings(); i++) {
            PictureLayerTiling* tiling = tilings->tiling_at(i);
            EXPECT_EQ(
                tiling->GetCurrentVisibleRectForTesting(),
                gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
                    tiling->contents_scale()));
        }
    }

    TEST_F(PictureLayerImplTest, ViewportRectForTilePriorityIsCached)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        gfx::Size layer_bounds(400, 400);
        SetupDefaultTrees(layer_bounds);

        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        gfx::Rect viewport_rect_for_tile_priority(0, 0, 100, 100);
        gfx::Transform transform_for_tile_priority;

        host_impl()->SetExternalTilePriorityConstraints(
            viewport_rect_for_tile_priority, transform_for_tile_priority);
        bool update_lcd_text = false;
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);

        EXPECT_EQ(viewport_rect_for_tile_priority,
            active_layer()->viewport_rect_for_tile_priority_in_content_space());

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        gfx::Rect another_viewport_rect_for_tile_priority(11, 11, 50, 50);
        host_impl()->SetExternalTilePriorityConstraints(
            another_viewport_rect_for_tile_priority, transform_for_tile_priority);

        // Didn't call UpdateDrawProperties yet. The viewport rect for tile priority
        // should remain to be the previously cached value.
        EXPECT_EQ(viewport_rect_for_tile_priority,
            active_layer()->viewport_rect_for_tile_priority_in_content_space());
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);

        // Now the UpdateDrawProperties is called. The viewport rect for tile
        // priority should be the latest value.
        EXPECT_EQ(another_viewport_rect_for_tile_priority,
            active_layer()->viewport_rect_for_tile_priority_in_content_space());
    }

    TEST_F(PictureLayerImplTest, ClonePartialInvalidation)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Rect layer_invalidation(150, 200, 30, 180);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> lost_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTreeWithFixedTileSize(lost_raster_source, gfx::Size(50, 50),
            Region());
        ActivateTree();
        // Add a unique tiling on the active tree.
        PictureLayerTiling* tiling = active_layer()->AddTiling(3.f);
        tiling->set_resolution(HIGH_RESOLUTION);
        tiling->CreateAllTilesForTesting();

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Then setup a new pending tree and activate it.
        SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
            gfx::Size(50, 50), layer_invalidation);

        EXPECT_EQ(1u, pending_layer()->num_tilings());
        EXPECT_EQ(3u, active_layer()->num_tilings());

        const PictureLayerTilingSet* tilings = pending_layer()->tilings();
        EXPECT_GT(tilings->num_tilings(), 0u);
        for (size_t i = 0; i < tilings->num_tilings(); ++i) {
            const PictureLayerTiling* tiling = tilings->tiling_at(i);
            gfx::Rect content_invalidation = gfx::ScaleToEnclosingRect(layer_invalidation, tiling->contents_scale());
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
            for (PictureLayerTiling::CoverageIterator iter(
                     tiling, tiling->contents_scale(),
                     gfx::Rect(tiling->tiling_size()));
                 iter; ++iter) {
                // We don't always have a tile, but when we do it's because it was
                // invalidated and it has the latest raster source.
                if (*iter) {
                    EXPECT_FALSE(iter.geometry_rect().IsEmpty());
                    EXPECT_EQ(pending_raster_source.get(),
                        prioritized_tiles[*iter].raster_source());
                    EXPECT_TRUE(iter.geometry_rect().Intersects(content_invalidation));
                } else {
                    // We don't create tiles in non-invalidated regions.
                    EXPECT_FALSE(iter.geometry_rect().Intersects(content_invalidation));
                }
            }
        }

        tilings = active_layer()->tilings();
        EXPECT_GT(tilings->num_tilings(), 0u);
        for (size_t i = 0; i < tilings->num_tilings(); ++i) {
            const PictureLayerTiling* tiling = tilings->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
            for (PictureLayerTiling::CoverageIterator iter(
                     tiling, tiling->contents_scale(),
                     gfx::Rect(tiling->tiling_size()));
                 iter; ++iter) {
                EXPECT_TRUE(*iter);
                EXPECT_FALSE(iter.geometry_rect().IsEmpty());
                // Raster source will be updated upon activation.
                EXPECT_EQ(active_raster_source.get(),
                    prioritized_tiles[*iter].raster_source());
            }
        }
    }

    TEST_F(PictureLayerImplTest, CloneFullInvalidation)
    {
        gfx::Size layer_bounds(300, 500);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupTreesWithInvalidation(pending_raster_source, active_raster_source,
            gfx::Rect(layer_bounds));

        EXPECT_EQ(pending_layer()->tilings()->num_tilings(),
            active_layer()->tilings()->num_tilings());

        const PictureLayerTilingSet* tilings = pending_layer()->tilings();
        EXPECT_GT(tilings->num_tilings(), 0u);
        for (size_t i = 0; i < tilings->num_tilings(); ++i) {
            VerifyAllPrioritizedTilesExistAndHaveRasterSource(
                tilings->tiling_at(i), pending_raster_source.get());
        }
    }

    TEST_F(PictureLayerImplTest, UpdateTilesCreatesTilings)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        active_layer()->ReleaseTileResources();
        EXPECT_FALSE(active_layer()->tilings());
        active_layer()->RecreateTileResources();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());

        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            6.f, // ideal contents scale
            3.f, // device scale
            2.f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(6.f * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        // If we change the page scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            6.6f, // ideal contents scale
            3.f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.6f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(6.6f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // If we change the device scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            7.26f, // ideal contents scale
            3.3f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(6u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(7.26f * low_res_factor,
            active_layer()->tilings()->tiling_at(3)->contents_scale());

        // If we change the device scale factor, but end up at the same total scale
        // factor somehow, then we don't get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            7.26f, // ideal contents scale
            2.2f, // device scale
            3.3f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(6u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(7.26f * low_res_factor,
            active_layer()->tilings()->tiling_at(3)->contents_scale());
    }

    TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighResTiling)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        pending_layer()->ReleaseTileResources();
        EXPECT_FALSE(pending_layer()->tilings());
        pending_layer()->RecreateTileResources();
        EXPECT_EQ(0u, pending_layer()->tilings()->num_tilings());

        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            6.f, // ideal contents scale
            3.f, // device scale
            2.f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the page scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            6.6f, // ideal contents scale
            3.f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.6f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            7.26f, // ideal contents scale
            3.3f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, but end up at the same total scale
        // factor somehow, then we don't get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            7.26f, // ideal contents scale
            2.2f, // device scale
            3.3f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());
    }

    TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone)
    {
        // This test makes sure that if a layer can have tilings, then a commit makes
        // it not able to have tilings (empty size), and then a future commit that
        // makes it valid again should be able to create tilings.
        gfx::Size layer_bounds(1300, 1900);

        scoped_refptr<FakeRasterSource> empty_raster_source = FakeRasterSource::CreateEmpty(layer_bounds);
        scoped_refptr<FakeRasterSource> valid_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(valid_raster_source);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());

        ActivateTree();
        SetupPendingTree(empty_raster_source);
        EXPECT_FALSE(pending_layer()->CanHaveTilings());
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        ASSERT_EQ(0u, pending_layer()->tilings()->num_tilings());

        ActivateTree();
        EXPECT_FALSE(active_layer()->CanHaveTilings());
        ASSERT_EQ(0u, active_layer()->tilings()->num_tilings());

        SetupPendingTree(valid_raster_source);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        ASSERT_EQ(0u, active_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, LowResTilingStaysOnActiveTree)
    {
        gfx::Size layer_bounds(1300, 1900);

        scoped_refptr<FakeRasterSource> valid_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> other_valid_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(valid_raster_source);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());

        ActivateTree();
        SetupPendingTree(other_valid_raster_source);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        auto* low_res_tiling = active_layer()->tilings()->FindTilingWithResolution(LOW_RESOLUTION);
        EXPECT_TRUE(low_res_tiling);

        ActivateTree();
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        auto* other_low_res_tiling = active_layer()->tilings()->FindTilingWithResolution(LOW_RESOLUTION);
        EXPECT_TRUE(other_low_res_tiling);
        EXPECT_EQ(low_res_tiling, other_low_res_tiling);
    }

    TEST_F(PictureLayerImplTest, ZoomOutCrash)
    {
        gfx::Size layer_bounds(1300, 1900);

        // Set up the high and low res tilings before pinch zoom.
        SetupDefaultTrees(layer_bounds);
        ResetTilingsAndRasterScales();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
        SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, 1.0f, 0.f, false);
        EXPECT_EQ(32.f, active_layer()->HighResTiling()->contents_scale());
        host_impl()->PinchGestureBegin();
        SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, 0.f, false);
        SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, 0.f, false);
        EXPECT_EQ(active_layer()->tilings()->NumHighResTilings(), 1);
    }

    TEST_F(PictureLayerImplTest, PinchGestureTilings)
    {
        gfx::Size layer_bounds(1300, 1900);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        // Set up the high and low res tilings before pinch zoom.
        SetupDefaultTrees(layer_bounds);
        ResetTilingsAndRasterScales();

        SetContentsScaleOnBothLayers(2.f, 1.0f, 2.f, 1.0f, 0.f, false);
        EXPECT_EQ(active_layer()->num_tilings(), 2u);
        EXPECT_EQ(pending_layer()->num_tilings(), 1u);
        EXPECT_EQ(active_layer()->tilings()->tiling_at(0)->contents_scale(), 2.f);
        EXPECT_EQ(active_layer()->tilings()->tiling_at(1)->contents_scale(),
            2.f * low_res_factor);
        // One of the tilings has to be a low resolution one.
        EXPECT_EQ(LOW_RESOLUTION,
            active_layer()->tilings()->tiling_at(1)->resolution());

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Start a pinch gesture.
        host_impl()->PinchGestureBegin();

        // Zoom out by a small amount. We should create a tiling at half
        // the scale (2/kMaxScaleRatioDuringPinch).
        SetContentsScaleOnBothLayers(1.8f, 1.0f, 1.8f, 1.0f, 0.f, false);
        EXPECT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(2.0f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.0f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(2.0f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());
        // Since we're pinching, we shouldn't create a low resolution tiling.
        EXPECT_FALSE(
            active_layer()->tilings()->FindTilingWithResolution(LOW_RESOLUTION));

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Zoom out further, close to our low-res scale factor. We should
        // use that tiling as high-res, and not create a new tiling.
        SetContentsScaleOnBothLayers(low_res_factor * 2.1f, 1.0f,
            low_res_factor * 2.1f, 1.0f, 0.f, false);
        EXPECT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FALSE(
            active_layer()->tilings()->FindTilingWithResolution(LOW_RESOLUTION));

        // Zoom in a lot now. Since we increase by increments of
        // kMaxScaleRatioDuringPinch, this will create a new tiling at 4.0.
        SetContentsScaleOnBothLayers(3.8f, 1.0f, 3.8f, 1.f, 0.f, false);
        EXPECT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(4.0f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        // Although one of the tilings matches the low resolution scale, it still
        // shouldn't be marked as low resolution since we're pinching.
        auto* low_res_tiling = active_layer()->tilings()->FindTilingWithScaleKey(4.f * low_res_factor);
        EXPECT_TRUE(low_res_tiling);
        EXPECT_NE(LOW_RESOLUTION, low_res_tiling->resolution());

        // Stop a pinch gesture.
        host_impl()->PinchGestureEnd();

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // After pinch ends, set the scale to what the raster scale was updated to
        // (checked above).
        SetContentsScaleOnBothLayers(4.0f, 1.0f, 4.0f, 1.f, 0.f, false);
        EXPECT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(4.0f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        // Now that we stopped pinching, the low resolution tiling that existed should
        // now be marked as low resolution.
        low_res_tiling = active_layer()->tilings()->FindTilingWithScaleKey(4.f * low_res_factor);
        EXPECT_TRUE(low_res_tiling);
        EXPECT_EQ(LOW_RESOLUTION, low_res_tiling->resolution());
    }

    TEST_F(PictureLayerImplTest, SnappedTilingDuringZoom)
    {
        gfx::Size layer_bounds(2600, 3800);
        SetupDefaultTrees(layer_bounds);

        ResetTilingsAndRasterScales();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());

        // Set up the high and low res tilings before pinch zoom.
        SetContentsScaleOnBothLayers(0.24f, 1.0f, 0.24f, 1.0f, 0.f, false);
        EXPECT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(0.24f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(0.0625f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Start a pinch gesture.
        host_impl()->PinchGestureBegin();

        // Zoom out by a small amount. We should create a tiling at half
        // the scale (1/kMaxScaleRatioDuringPinch).
        SetContentsScaleOnBothLayers(0.2f, 1.0f, 0.2f, 1.0f, 0.f, false);
        EXPECT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(0.24f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(0.12f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(0.0625,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Zoom out further, close to our low-res scale factor. We should
        // use that tiling as high-res, and not create a new tiling.
        SetContentsScaleOnBothLayers(0.1f, 1.0f, 0.1f, 1.0f, 0.f, false);
        EXPECT_EQ(3u, active_layer()->tilings()->num_tilings());

        // Zoom in. 0.25(desired_scale) should be snapped to 0.24 during zoom-in
        // because 0.25(desired_scale) is within the ratio(1.2).
        SetContentsScaleOnBothLayers(0.25f, 1.0f, 0.25f, 1.0f, 0.f, false);
        EXPECT_EQ(3u, active_layer()->tilings()->num_tilings());

        // Zoom in a lot. Since we move in factors of two, we should get a scale that
        // is a power of 2 times 0.24.
        SetContentsScaleOnBothLayers(1.f, 1.0f, 1.f, 1.0f, 0.f, false);
        EXPECT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.92f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
    }

    TEST_F(PictureLayerImplTest, CleanUpTilings)
    {
        gfx::Size layer_bounds(1300, 1900);

        std::vector<PictureLayerTiling*> used_tilings;

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        float scale = 1.f;
        float page_scale = 1.f;

        SetupDefaultTrees(layer_bounds);
        active_layer()->SetHasWillChangeTransformHint(true);
        EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        // Ensure UpdateTiles won't remove any tilings. Note this is unrelated to
        // |used_tilings| variable, and it's here only to ensure that active_layer()
        // won't remove tilings before the test has a chance to verify behavior.
        active_layer()->MarkAllTilingsUsed();

        // We only have ideal tilings, so they aren't removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        host_impl()->PinchGestureBegin();

        // Changing the ideal but not creating new tilings.
        scale = 1.5f;
        page_scale = 1.5f;
        SetContentsScaleOnBothLayers(scale, 1.f, page_scale, 1.f, 0.f, false);
        EXPECT_FLOAT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        // The tilings are still our target scale, so they aren't removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        host_impl()->PinchGestureEnd();

        // Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2.
        scale = 1.2f;
        page_scale = 1.2f;
        SetContentsScaleOnBothLayers(1.2f, 1.f, page_scale, 1.f, 0.f, false);
        ASSERT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(3)->contents_scale());

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Mark the non-ideal tilings as used. They won't be removed.
        used_tilings.clear();
        used_tilings.push_back(active_layer()->tilings()->tiling_at(1));
        used_tilings.push_back(active_layer()->tilings()->tiling_at(3));
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(4u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());
        EXPECT_FLOAT_EQ(1.f * low_res_factor,
            active_layer()->tilings()->tiling_at(3)->contents_scale());

        // Now move the ideal scale to 0.5. Our target stays 1.2.
        SetContentsScaleOnBothLayers(0.5f, 1.f, page_scale, 1.f, 0.f, false);

        // The high resolution tiling is between target and ideal, so is not
        // removed.  The low res tiling for the old ideal=1.0 scale is removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // Now move the ideal scale to 1.0. Our target stays 1.2.
        SetContentsScaleOnBothLayers(1.f, 1.f, page_scale, 1.f, 0.f, false);

        // All the tilings are between are target and the ideal, so they are not
        // removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.1f, 1.f, page_scale, 1.f,
            0.f, false);

        // Because the pending layer's ideal scale is still 1.0, our tilings fall
        // in the range [1.0,1.2] and are kept.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
        // 1.2 still.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.1f, 1.f, page_scale, 1.f,
            0.f, false);

        // Our 1.0 tiling now falls outside the range between our ideal scale and our
        // target raster scale. But it is in our used tilings set, so nothing is
        // deleted.
        used_tilings.clear();
        used_tilings.push_back(active_layer()->tilings()->tiling_at(1));
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
        EXPECT_FLOAT_EQ(1.2f * low_res_factor,
            active_layer()->tilings()->tiling_at(2)->contents_scale());

        // If we remove it from our used tilings set, it is outside the range to keep
        // so it is deleted.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.2f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_FLOAT_EQ(1.2 * low_res_factor,
            active_layer()->tilings()->tiling_at(1)->contents_scale());
    }

    TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation)
    {
        // Make sure this layer covers multiple tiles, since otherwise low
        // res won't get created because it is too small.
        gfx::Size tile_size(host_impl()->settings().default_tile_size);
        // Avoid max untiled layer size heuristics via fixed tile size.
        gfx::Size layer_bounds(tile_size.width() + 1, tile_size.height() + 1);
        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        float contents_scale = 1.f;
        float device_scale = 1.f;
        float page_scale = 1.f;
        float maximum_animation_scale = 1.f;
        float starting_animation_scale = 0.f;
        bool animating_transform = true;

        ResetTilingsAndRasterScales();

        // Animating, so don't create low res even if there isn't one already.
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
        EXPECT_BOTH_EQ(num_tilings(), 1u);

        // Stop animating, low res gets created.
        animating_transform = false;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);
        EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(), low_res_factor);
        EXPECT_EQ(active_layer()->num_tilings(), 2u);
        EXPECT_EQ(pending_layer()->num_tilings(), 1u);

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Page scale animation, new high res, but no low res. We still have
        // a tiling at the previous scale, it's just not marked as low res on the
        // active layer. The pending layer drops non-ideal tilings.
        contents_scale = 2.f;
        page_scale = 2.f;
        maximum_animation_scale = 2.f;
        animating_transform = true;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
        EXPECT_FALSE(active_layer()->LowResTiling());
        EXPECT_FALSE(pending_layer()->LowResTiling());
        EXPECT_EQ(3u, active_layer()->num_tilings());
        EXPECT_EQ(1u, pending_layer()->num_tilings());

        // Stop animating, new low res gets created for final page scale.
        animating_transform = false;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);
        EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(),
            2.f * low_res_factor);
        EXPECT_EQ(4u, active_layer()->num_tilings());
        EXPECT_EQ(1u, pending_layer()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers)
    {
        gfx::Size layer_bounds(host_impl()->settings().default_tile_size);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupTrees(pending_raster_source, active_raster_source);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        float device_scale = 1.f;
        float page_scale = 1.f;
        float maximum_animation_scale = 1.f;
        float starting_animation_scale = 0.f;
        bool animating_transform = false;

        // Contents exactly fit on one tile at scale 1, no low res.
        float contents_scale = 1.f;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
        EXPECT_BOTH_EQ(num_tilings(), 1u);

        ResetTilingsAndRasterScales();

        // Contents that are smaller than one tile, no low res.
        contents_scale = 0.123f;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
        EXPECT_BOTH_EQ(num_tilings(), 1u);

        // TODO(danakj): Remove these when raster scale doesn't get fixed?
        ResetTilingsAndRasterScales();

        // Any content bounds that would create more than one tile will
        // generate a low res tiling.
        contents_scale = 2.5f;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale);
        EXPECT_EQ(active_layer()->LowResTiling()->contents_scale(),
            contents_scale * low_res_factor);
        EXPECT_FALSE(pending_layer()->LowResTiling());
        EXPECT_EQ(active_layer()->num_tilings(), 2u);
        EXPECT_EQ(pending_layer()->num_tilings(), 1u);

        // Mask layers dont create low res since they always fit on one tile.
        std::unique_ptr<FakePictureLayerImpl> mask = FakePictureLayerImpl::CreateMaskWithRasterSource(
            host_impl()->pending_tree(), 3, pending_raster_source);
        mask->SetBounds(layer_bounds);
        mask->SetDrawsContent(true);
        pending_layer()->test_properties()->SetMaskLayer(std::move(mask));
        pending_layer()->SetHasRenderSurface(true);
        RebuildPropertyTreesOnPendingTree();
        host_impl()->pending_tree()->UpdateDrawProperties(false);

        FakePictureLayerImpl* mask_raw = static_cast<FakePictureLayerImpl*>(
            pending_layer()->test_properties()->mask_layer);
        // We did an UpdateDrawProperties above, which will set a contents scale on
        // the mask layer, so allow us to reset the contents scale.
        mask_raw->ReleaseTileResources();
        mask_raw->RecreateTileResources();

        SetupDrawPropertiesAndUpdateTiles(
            mask_raw, contents_scale, device_scale, page_scale,
            maximum_animation_scale, starting_animation_scale, animating_transform);
        EXPECT_EQ(mask_raw->HighResTiling()->contents_scale(), contents_scale);
        EXPECT_EQ(mask_raw->num_tilings(), 1u);
    }

    TEST_F(PictureLayerImplTest, HugeMasksGetScaledDown)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size layer_bounds(1000, 1000);

        scoped_refptr<FakeRasterSource> valid_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(valid_raster_source);

        std::unique_ptr<FakePictureLayerImpl> mask_ptr = FakePictureLayerImpl::CreateMaskWithRasterSource(
            host_impl()->pending_tree(), 3, valid_raster_source);
        mask_ptr->SetBounds(layer_bounds);
        mask_ptr->SetDrawsContent(true);
        pending_layer()->test_properties()->SetMaskLayer(std::move(mask_ptr));
        pending_layer()->test_properties()->force_render_surface = true;

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        FakePictureLayerImpl* pending_mask = static_cast<FakePictureLayerImpl*>(
            pending_layer()->test_properties()->mask_layer);

        EXPECT_EQ(1.f, pending_mask->HighResTiling()->contents_scale());
        EXPECT_EQ(1u, pending_mask->num_tilings());

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            pending_mask->HighResTiling()->AllTilesForTesting());

        ActivateTree();

        FakePictureLayerImpl* active_mask = static_cast<FakePictureLayerImpl*>(
            host_impl()->active_tree()->LayerById(pending_mask->id()));

        // Mask layers have a tiling with a single tile in it.
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        // The mask resource exists.
        ResourceId mask_resource_id;
        gfx::Size mask_texture_size;
        active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
        EXPECT_NE(0u, mask_resource_id);
        EXPECT_EQ(active_mask->bounds(), mask_texture_size);

        // Drop resources and recreate them, still the same.
        pending_mask->ReleaseTileResources();
        active_mask->ReleaseTileResources();
        pending_mask->RecreateTileResources();
        active_mask->RecreateTileResources();
        SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        active_mask->HighResTiling()->CreateAllTilesForTesting();
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        EXPECT_NE(0u, mask_resource_id);
        EXPECT_EQ(active_mask->bounds(), mask_texture_size);

        // Resize larger than the max texture size.
        int max_texture_size = host_impl()->resource_provider()->max_texture_size();
        gfx::Size huge_bounds(max_texture_size + 1, 10);
        scoped_refptr<FakeRasterSource> huge_raster_source = FakeRasterSource::CreateFilled(huge_bounds);

        SetupPendingTree(huge_raster_source);
        pending_mask->SetBounds(huge_bounds);
        pending_mask->SetRasterSourceOnPending(huge_raster_source, Region());

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        // The mask tiling gets scaled down.
        EXPECT_LT(pending_mask->HighResTiling()->contents_scale(), 1.f);
        EXPECT_EQ(1u, pending_mask->num_tilings());

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            pending_mask->HighResTiling()->AllTilesForTesting());

        ActivateTree();

        // Mask layers have a tiling with a single tile in it.
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        // The mask resource exists.
        active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
        EXPECT_NE(0u, mask_resource_id);
        gfx::Size expected_size = active_mask->bounds();
        expected_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
        EXPECT_EQ(expected_size, mask_texture_size);

        // Drop resources and recreate them, still the same.
        pending_mask->ReleaseTileResources();
        active_mask->ReleaseTileResources();
        pending_mask->RecreateTileResources();
        active_mask->RecreateTileResources();
        SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        active_mask->HighResTiling()->CreateAllTilesForTesting();
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        EXPECT_NE(0u, mask_resource_id);
        EXPECT_EQ(expected_size, mask_texture_size);

        // Do another activate, the same holds.
        SetupPendingTree(huge_raster_source);
        ActivateTree();
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        active_layer()->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
        EXPECT_EQ(expected_size, mask_texture_size);
        EXPECT_EQ(0u, mask_resource_id);

        // Resize even larger, so that the scale would be smaller than the minimum
        // contents scale. Then the layer should no longer have any tiling.
        float min_contents_scale = host_impl()->settings().minimum_contents_scale;
        gfx::Size extra_huge_bounds(max_texture_size / min_contents_scale + 1, 10);
        scoped_refptr<FakeRasterSource> extra_huge_raster_source = FakeRasterSource::CreateFilled(extra_huge_bounds);

        SetupPendingTree(extra_huge_raster_source);
        pending_mask->SetBounds(extra_huge_bounds);
        pending_mask->SetRasterSourceOnPending(extra_huge_raster_source, Region());

        EXPECT_FALSE(pending_mask->CanHaveTilings());

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        EXPECT_EQ(0u, pending_mask->num_tilings());
    }

    TEST_F(PictureLayerImplTest, ScaledMaskLayer)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size layer_bounds(1000, 1000);

        SetInitialDeviceScaleFactor(1.3f);

        scoped_refptr<FakeRasterSource> valid_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(valid_raster_source);

        std::unique_ptr<FakePictureLayerImpl> mask_ptr = FakePictureLayerImpl::CreateMaskWithRasterSource(
            host_impl()->pending_tree(), 3, valid_raster_source);
        mask_ptr->SetBounds(layer_bounds);
        mask_ptr->SetDrawsContent(true);
        pending_layer()->test_properties()->SetMaskLayer(std::move(mask_ptr));
        pending_layer()->test_properties()->force_render_surface = true;

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        FakePictureLayerImpl* pending_mask = static_cast<FakePictureLayerImpl*>(
            pending_layer()->test_properties()->mask_layer);

        // Masks are scaled, and do not have a low res tiling.
        EXPECT_EQ(1.3f, pending_mask->HighResTiling()->contents_scale());
        EXPECT_EQ(1u, pending_mask->num_tilings());

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            pending_mask->HighResTiling()->AllTilesForTesting());

        ActivateTree();

        FakePictureLayerImpl* active_mask = static_cast<FakePictureLayerImpl*>(
            host_impl()->active_tree()->LayerById(pending_mask->id()));

        // Mask layers have a tiling with a single tile in it.
        EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size());
        // The mask resource exists.
        ResourceId mask_resource_id;
        gfx::Size mask_texture_size;
        active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
        EXPECT_NE(0u, mask_resource_id);
        gfx::Size expected_mask_texture_size = gfx::ScaleToCeiledSize(active_mask->bounds(), 1.3f);
        EXPECT_EQ(mask_texture_size, expected_mask_texture_size);
    }

    TEST_F(PictureLayerImplTest, ReleaseTileResources)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());

        // All tilings should be removed when losing output surface.
        active_layer()->ReleaseTileResources();
        EXPECT_FALSE(active_layer()->tilings());
        active_layer()->RecreateTileResources();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
        pending_layer()->ReleaseTileResources();
        EXPECT_FALSE(pending_layer()->tilings());
        pending_layer()->RecreateTileResources();
        EXPECT_EQ(0u, pending_layer()->tilings()->num_tilings());

        // This should create new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            1.f, // ideal contents scale
            1.f, // device scale
            1.f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation_scale
            false);
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
    }

    // ReleaseResources should behave identically to ReleaseTileResources.
    TEST_F(PictureLayerImplTest, ReleaseResources)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());

        // All tilings should be removed when losing output surface.
        active_layer()->ReleaseResources();
        EXPECT_FALSE(active_layer()->tilings());
        active_layer()->RecreateTileResources();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
        pending_layer()->ReleaseResources();
        EXPECT_FALSE(pending_layer()->tilings());
        pending_layer()->RecreateTileResources();
        EXPECT_EQ(0u, pending_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, ClampTilesToMaxTileSize)
    {
        gfx::Size layer_bounds(5000, 5000);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(pending_raster_source);
        EXPECT_GE(pending_layer()->tilings()->num_tilings(), 1u);

        pending_layer()->tilings()->tiling_at(0)->CreateAllTilesForTesting();

        // The default value.
        EXPECT_EQ(gfx::Size(256, 256).ToString(),
            host_impl()->settings().default_tile_size.ToString());

        Tile* tile = pending_layer()->tilings()->tiling_at(0)->AllTilesForTesting()[0];
        EXPECT_EQ(gfx::Size(256, 256).ToString(),
            tile->content_rect().size().ToString());

        ResetTilingsAndRasterScales();

        // Change the max texture size on the output surface context.
        std::unique_ptr<TestWebGraphicsContext3D> context = TestWebGraphicsContext3D::Create();
        context->set_max_texture_size(140);
        ResetCompositorFrameSink(
            FakeCompositorFrameSink::Create3d(std::move(context)));

        SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());

        pending_layer()->tilings()->tiling_at(0)->CreateAllTilesForTesting();

        // Verify the tiles are not larger than the context's max texture size.
        tile = pending_layer()->tilings()->tiling_at(0)->AllTilesForTesting()[0];
        EXPECT_GE(140, tile->content_rect().width());
        EXPECT_GE(140, tile->content_rect().height());
    }

    TEST_F(PictureLayerImplTest, ClampSingleTileToToMaxTileSize)
    {
        gfx::Size layer_bounds(500, 500);
        SetupDefaultTrees(layer_bounds);
        EXPECT_GE(active_layer()->tilings()->num_tilings(), 1u);

        active_layer()->tilings()->tiling_at(0)->CreateAllTilesForTesting();

        // The default value. The layer is smaller than this.
        EXPECT_EQ(gfx::Size(512, 512).ToString(),
            host_impl()->settings().max_untiled_layer_size.ToString());

        // There should be a single tile since the layer is small.
        PictureLayerTiling* high_res_tiling = active_layer()->tilings()->tiling_at(0);
        EXPECT_EQ(1u, high_res_tiling->AllTilesForTesting().size());

        ResetTilingsAndRasterScales();

        // Change the max texture size on the output surface context.
        std::unique_ptr<TestWebGraphicsContext3D> context = TestWebGraphicsContext3D::Create();
        context->set_max_texture_size(140);
        ResetCompositorFrameSink(
            FakeCompositorFrameSink::Create3d(std::move(context)));

        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        ASSERT_LE(1u, active_layer()->tilings()->num_tilings());

        active_layer()->tilings()->tiling_at(0)->CreateAllTilesForTesting();

        // There should be more than one tile since the max texture size won't cover
        // the layer.
        high_res_tiling = active_layer()->tilings()->tiling_at(0);
        EXPECT_LT(1u, high_res_tiling->AllTilesForTesting().size());

        // Verify the tiles are not larger than the context's max texture size.
        Tile* tile = active_layer()->tilings()->tiling_at(0)->AllTilesForTesting()[0];
        EXPECT_GE(140, tile->content_rect().width());
        EXPECT_GE(140, tile->content_rect().height());
    }

    TEST_F(PictureLayerImplTest, DisallowTileDrawQuads)
    {
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();

        gfx::Size layer_bounds(1300, 1900);
        gfx::Rect layer_rect(layer_bounds);

        gfx::Rect layer_invalidation(150, 200, 30, 180);
        SetupDefaultTreesWithInvalidation(layer_bounds, layer_invalidation);

        active_layer()->SetContentsOpaque(true);
        active_layer()->draw_properties().visible_layer_rect = gfx::Rect(layer_bounds);

        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        ASSERT_EQ(1u, render_pass->quad_list.size());
        EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
            render_pass->quad_list.front()->material);
        EXPECT_EQ(render_pass->quad_list.front()->rect, layer_rect);
        EXPECT_EQ(render_pass->quad_list.front()->opaque_rect, layer_rect);
        EXPECT_EQ(render_pass->quad_list.front()->visible_rect, layer_rect);
    }

    TEST_F(PictureLayerImplTest, ResourcelessPartialRecording)
    {
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();

        gfx::Size tile_size(400, 400);
        gfx::Size layer_bounds(700, 650);
        gfx::Rect layer_rect(layer_bounds);
        SetInitialDeviceScaleFactor(2.f);

        gfx::Rect recorded_viewport(20, 30, 40, 50);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds, recorded_viewport);

        SetupPendingTree(active_raster_source);
        ActivateTree();

        active_layer()->SetContentsOpaque(true);
        gfx::Rect visible_rect(30, 35, 10, 5);
        active_layer()->draw_properties().visible_layer_rect = visible_rect;

        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        gfx::Rect scaled_visible = gfx::ScaleToEnclosingRect(visible_rect, 2.f);
        gfx::Rect scaled_recorded = gfx::ScaleToEnclosingRect(recorded_viewport, 2.f);
        gfx::Rect quad_visible = gfx::IntersectRects(scaled_visible, scaled_recorded);

        ASSERT_EQ(1U, render_pass->quad_list.size());
        EXPECT_EQ(DrawQuad::PICTURE_CONTENT,
            render_pass->quad_list.front()->material);
        const DrawQuad* quad = render_pass->quad_list.front();
        EXPECT_EQ(quad_visible, quad->rect);
        EXPECT_EQ(quad_visible, quad->opaque_rect);
        EXPECT_EQ(quad_visible, quad->visible_rect);
    }

    TEST_F(PictureLayerImplTest, ResourcelessEmptyRecording)
    {
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();

        gfx::Size layer_bounds(700, 650);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds, gfx::Rect());
        SetupPendingTree(active_raster_source);
        ActivateTree();

        active_layer()->SetContentsOpaque(true);
        active_layer()->draw_properties().visible_layer_rect = gfx::Rect(layer_bounds);

        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        EXPECT_EQ(0U, render_pass->quad_list.size());
    }

    TEST_F(PictureLayerImplTest, SolidColorLayerHasVisibleFullCoverage)
    {
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();

        gfx::Size layer_bounds(1500, 1500);
        gfx::Rect visible_rect(250, 250, 1000, 1000);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilledSolidColor(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilledSolidColor(layer_bounds);

        SetupTrees(pending_raster_source, active_raster_source);

        active_layer()->draw_properties().visible_layer_rect = visible_rect;

        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        Region remaining = visible_rect;
        for (auto* quad : render_pass->quad_list) {
            EXPECT_TRUE(visible_rect.Contains(quad->rect));
            EXPECT_TRUE(remaining.Contains(quad->rect));
            remaining.Subtract(quad->rect);
        }

        EXPECT_TRUE(remaining.IsEmpty());
    }

    TEST_F(PictureLayerImplTest, TileScalesWithSolidColorRasterSource)
    {
        gfx::Size layer_bounds(200, 200);
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilledSolidColor(layer_bounds);

        SetupTrees(pending_raster_source, active_raster_source);
        // Solid color raster source should not allow tilings at any scale.
        EXPECT_FALSE(active_layer()->CanHaveTilings());
        EXPECT_EQ(0.f, active_layer()->ideal_contents_scale());

        // Activate non-solid-color pending raster source makes active layer can have
        // tilings.
        ActivateTree();
        EXPECT_TRUE(active_layer()->CanHaveTilings());
        EXPECT_GT(active_layer()->ideal_contents_scale(), 0.f);
    }

    TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles)
    {
        gfx::Size layer_bounds(200, 200);

        gfx::Transform transform;
        gfx::Rect viewport(0, 0, 100, 200);
        host_impl()->SetExternalTilePriorityConstraints(viewport, transform);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, gfx::Size(100, 100),
            Region());

        EXPECT_EQ(1u, pending_layer()->num_tilings());
        EXPECT_EQ(
            viewport,
            pending_layer()->viewport_rect_for_tile_priority_in_content_space());

        base::TimeTicks time_ticks;
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        pending_layer()->UpdateTiles();

        int num_visible = 0;
        int num_offscreen = 0;

        std::unique_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        for (; !queue->IsEmpty(); queue->Pop()) {
            const PrioritizedTile& prioritized_tile = queue->Top();
            DCHECK(prioritized_tile.tile());
            if (prioritized_tile.priority().distance_to_visible == 0.f) {
                EXPECT_TRUE(prioritized_tile.tile()->required_for_activation());
                num_visible++;
            } else {
                EXPECT_FALSE(prioritized_tile.tile()->required_for_activation());
                num_offscreen++;
            }
        }

        EXPECT_GT(num_visible, 0);
        EXPECT_GT(num_offscreen, 0);
    }

    TEST_F(NoLowResPictureLayerImplTest,
        TileOutsideOfViewportForTilePriorityNotRequired)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(400, 400);
        gfx::Rect external_viewport_for_tile_priority(400, 200);
        gfx::Rect visible_layer_rect(200, 400);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        ASSERT_EQ(1u, pending_layer()->num_tilings());
        ASSERT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale());

        // Set external viewport for tile priority.
        gfx::Transform transform;
        gfx::Transform transform_for_tile_priority;
        host_impl()->SetExternalTilePriorityConstraints(
            external_viewport_for_tile_priority, transform_for_tile_priority);
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        // Set visible content rect that is different from
        // external_viewport_for_tile_priority.
        pending_layer()->draw_properties().visible_layer_rect = visible_layer_rect;
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));
        pending_layer()->UpdateTiles();

        // Intersect the two rects. Any tile outside should not be required for
        // activation.
        gfx::Rect viewport_for_tile_priority = pending_layer()->viewport_rect_for_tile_priority_in_content_space();
        viewport_for_tile_priority.Intersect(pending_layer()->visible_layer_rect());

        EXPECT_TRUE(pending_layer()->HighResTiling()->AllTilesForTesting().empty());

        int num_inside = 0;
        int num_outside = 0;
        for (PictureLayerTiling::CoverageIterator iter(
                 active_layer()->HighResTiling(), 1.f, gfx::Rect(layer_bounds));
             iter; ++iter) {
            if (!*iter)
                continue;
            Tile* tile = *iter;
            if (viewport_for_tile_priority.Intersects(iter.geometry_rect())) {
                num_inside++;
                // Mark everything in viewport for tile priority as ready to draw.
                TileDrawInfo& draw_info = tile->draw_info();
                draw_info.SetSolidColorForTesting(SK_ColorRED);
            } else {
                num_outside++;
                EXPECT_FALSE(tile->required_for_activation());
            }
        }

        EXPECT_GT(num_inside, 0);
        EXPECT_GT(num_outside, 0);

        // Activate and draw active layer.
        host_impl()->ActivateSyncTree();
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);
        active_layer()->draw_properties().visible_layer_rect = visible_layer_rect;

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        // All tiles in activation rect is ready to draw.
        EXPECT_EQ(0u, data.num_missing_tiles);
        EXPECT_EQ(0u, data.num_incomplete_tiles);
        EXPECT_FALSE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, HighResTileIsComplete)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        // All high res tiles have resources.
        std::vector<Tile*> tiles = active_layer()->tilings()->tiling_at(0)->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        // All high res tiles drew, nothing was incomplete.
        EXPECT_EQ(9u, render_pass->quad_list.size());
        EXPECT_EQ(0u, data.num_missing_tiles);
        EXPECT_EQ(0u, data.num_incomplete_tiles);
        EXPECT_FALSE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, HighResTileIsIncomplete)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        EXPECT_EQ(1u, render_pass->quad_list.size());
        EXPECT_EQ(1u, data.num_missing_tiles);
        EXPECT_EQ(0u, data.num_incomplete_tiles);
        EXPECT_TRUE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, HighResTileIsIncompleteLowResComplete)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        std::vector<Tile*> low_tiles = active_layer()->tilings()->tiling_at(1)->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            low_tiles);

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        EXPECT_EQ(1u, render_pass->quad_list.size());
        EXPECT_EQ(0u, data.num_missing_tiles);
        EXPECT_EQ(1u, data.num_incomplete_tiles);
        EXPECT_TRUE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, LowResTileIsIncomplete)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        // All high res tiles have resources except one.
        std::vector<Tile*> high_tiles = active_layer()->tilings()->tiling_at(0)->AllTilesForTesting();
        high_tiles.erase(high_tiles.begin());
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            high_tiles);

        // All low res tiles have resources.
        std::vector<Tile*> low_tiles = active_layer()->tilings()->tiling_at(1)->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            low_tiles);

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        // The missing high res tile was replaced by a low res tile.
        EXPECT_EQ(9u, render_pass->quad_list.size());
        EXPECT_EQ(0u, data.num_missing_tiles);
        EXPECT_EQ(1u, data.num_incomplete_tiles);
        EXPECT_FALSE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest,
        HighResAndIdealResTileIsCompleteWhenRasterScaleIsNotIdeal)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);
        gfx::Size viewport_size(400, 400);

        host_impl()->SetViewportSize(viewport_size);
        SetInitialDeviceScaleFactor(2.f);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());
        active_layer()->SetHasWillChangeTransformHint(true);

        // One ideal tile exists, this will get used when drawing.
        std::vector<Tile*> ideal_tiles;
        EXPECT_EQ(2.f, active_layer()->HighResTiling()->contents_scale());
        ideal_tiles.push_back(active_layer()->HighResTiling()->TileAt(0, 0));
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            ideal_tiles);

        // Due to layer scale throttling, the raster contents scale is changed to 1,
        // while the ideal is still 2.
        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        SetupDrawPropertiesAndUpdateTiles(active_layer(), 2.f, 1.f, 1.f, 1.f, 0.f,
            false);

        EXPECT_EQ(1.f, active_layer()->HighResTiling()->contents_scale());
        EXPECT_EQ(1.f, active_layer()->raster_contents_scale());
        EXPECT_EQ(2.f, active_layer()->ideal_contents_scale());

        // Both tilings still exist.
        EXPECT_EQ(2.f, active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_EQ(1.f, active_layer()->tilings()->tiling_at(1)->contents_scale());

        // All high res tiles have resources.
        std::vector<Tile*> high_tiles = active_layer()->HighResTiling()->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            high_tiles);

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        // All high res tiles drew, and the one ideal res tile drew.
        ASSERT_GT(render_pass->quad_list.size(), 9u);
        EXPECT_EQ(gfx::Rect(0, 0, 99, 99), render_pass->quad_list.front()->rect);
        EXPECT_EQ(gfx::RectF(0.f, 0.f, 99.f, 99.f),
            TileDrawQuad::MaterialCast(render_pass->quad_list.front())
                ->tex_coord_rect);
        EXPECT_EQ(gfx::Rect(99, 0, 100, 99),
            render_pass->quad_list.ElementAt(1)->rect);
        EXPECT_EQ(gfx::RectF(49.5f, 0.f, 50.f, 49.5f),
            TileDrawQuad::MaterialCast(render_pass->quad_list.ElementAt(1))
                ->tex_coord_rect);

        // Neither the high res nor the ideal tiles were considered as incomplete.
        EXPECT_EQ(0u, data.num_missing_tiles);
        EXPECT_EQ(0u, data.num_incomplete_tiles);
        EXPECT_FALSE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, AppendQuadsDataForCheckerboard)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);
        gfx::Rect recorded_viewport(0, 0, 150, 150);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds, recorded_viewport);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        EXPECT_EQ(1u, render_pass->quad_list.size());
        EXPECT_EQ(1u, data.num_missing_tiles);
        EXPECT_EQ(0u, data.num_incomplete_tiles);
        EXPECT_EQ(40000, data.checkerboarded_visible_content_area);
        EXPECT_EQ(17500, data.checkerboarded_no_recording_content_area);
        EXPECT_EQ(22500, data.checkerboarded_needs_raster_content_area);
        EXPECT_TRUE(active_layer()->only_used_low_res_last_append_quads());
    }

    TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveAllReady)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size,
            gfx::Rect(layer_bounds));

        active_layer()->SetAllTilesReady();

        // All active tiles ready, so pending can only activate with all high res
        // tiles.
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        EXPECT_FALSE(pending_layer()->LowResTiling());

        AssertAllTilesRequired(pending_layer()->HighResTiling());
    }

    TEST_F(PictureLayerImplTest, HighResRequiredWhenMissingHighResFlagOn)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        // No invalidation.
        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        // Verify active tree not ready.
        Tile* some_active_tile = active_layer()->HighResTiling()->AllTilesForTesting()[0];
        EXPECT_FALSE(some_active_tile->draw_info().IsReadyToDraw());

        // When high res are required, all tiles in active high res tiling should be
        // required for activation.
        host_impl()->SetRequiresHighResToDraw();

        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        EXPECT_FALSE(pending_layer()->LowResTiling());
        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        active_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        EXPECT_TRUE(pending_layer()->HighResTiling()->AllTilesForTesting().empty());
        AssertAllTilesRequired(active_layer()->HighResTiling());
        AssertNoTilesRequired(active_layer()->LowResTiling());
    }

    TEST_F(PictureLayerImplTest, AllHighResRequiredEvenIfNotChanged)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        Tile* some_active_tile = active_layer()->HighResTiling()->AllTilesForTesting()[0];
        EXPECT_FALSE(some_active_tile->draw_info().IsReadyToDraw());

        // Since there are no invalidations, pending tree should have no tiles.
        EXPECT_TRUE(pending_layer()->HighResTiling()->AllTilesForTesting().empty());
        EXPECT_FALSE(pending_layer()->LowResTiling());

        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        active_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        AssertAllTilesRequired(active_layer()->HighResTiling());
        AssertNoTilesRequired(active_layer()->LowResTiling());
    }

    TEST_F(PictureLayerImplTest, DisallowRequiredForActivation)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        Tile* some_active_tile = active_layer()->HighResTiling()->AllTilesForTesting()[0];
        EXPECT_FALSE(some_active_tile->draw_info().IsReadyToDraw());

        EXPECT_TRUE(pending_layer()->HighResTiling()->AllTilesForTesting().empty());
        EXPECT_FALSE(pending_layer()->LowResTiling());
        active_layer()->HighResTiling()->set_can_require_tiles_for_activation(false);
        active_layer()->LowResTiling()->set_can_require_tiles_for_activation(false);
        pending_layer()->HighResTiling()->set_can_require_tiles_for_activation(false);

        // If we disallow required for activation, no tiles can be required.
        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        active_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        AssertNoTilesRequired(active_layer()->HighResTiling());
        AssertNoTilesRequired(active_layer()->LowResTiling());
    }

    TEST_F(PictureLayerImplTest, NothingRequiredIfActiveMissingTiles)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        // This raster source will create tilings, but has no recordings so will not
        // create any tiles.  This is attempting to simulate scrolling past the end of
        // recorded content on the active layer, where the recordings are so far away
        // that no tiles are created.
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds, gfx::Rect());

        SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
            tile_size, Region());

        // Active layer has tilings, but no tiles due to missing recordings.
        EXPECT_TRUE(active_layer()->CanHaveTilings());
        EXPECT_EQ(active_layer()->tilings()->num_tilings(), 2u);
        EXPECT_EQ(active_layer()->HighResTiling()->AllTilesForTesting().size(), 0u);

        // Since the active layer has no tiles at all, the pending layer doesn't
        // need content in order to activate.
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        EXPECT_FALSE(pending_layer()->LowResTiling());

        AssertNoTilesRequired(pending_layer()->HighResTiling());
    }

    TEST_F(PictureLayerImplTest, HighResRequiredIfActiveCantHaveTiles)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateEmpty(layer_bounds);
        SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
            tile_size, Region());

        // Active layer can't have tiles.
        EXPECT_FALSE(active_layer()->CanHaveTilings());

        // All high res tiles required.  This should be considered identical
        // to the case where there is no active layer, to avoid flashing content.
        // This can happen if a layer exists for a while and switches from
        // not being able to have content to having content.
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        EXPECT_FALSE(pending_layer()->LowResTiling());

        AssertAllTilesRequired(pending_layer()->HighResTiling());
    }

    TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveHasDifferentBounds)
    {
        gfx::Size pending_layer_bounds(400, 400);
        gfx::Size active_layer_bounds(200, 200);
        gfx::Size tile_size(100, 100);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(pending_layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(active_layer_bounds);

        SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
            tile_size, Region());

        // Since the active layer has different bounds, the pending layer needs all
        // high res tiles in order to activate.
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        EXPECT_FALSE(pending_layer()->LowResTiling());
        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        active_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        AssertAllTilesRequired(pending_layer()->HighResTiling());
        AssertAllTilesRequired(active_layer()->HighResTiling());
        AssertNoTilesRequired(active_layer()->LowResTiling());
    }

    TEST_F(PictureLayerImplTest, ActivateUninitializedLayer)
    {
        gfx::Size layer_bounds(400, 400);
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->CreatePendingTree();
        LayerTreeImpl* pending_tree = host_impl()->pending_tree();

        std::unique_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id(),
            pending_raster_source);
        pending_layer->SetDrawsContent(true);
        pending_tree->SetRootLayerForTesting(std::move(pending_layer));
        pending_tree->BuildLayerListForTesting();

        FakePictureLayerImpl* raw_pending_layer = static_cast<FakePictureLayerImpl*>(
            host_impl()->pending_tree()->LayerById(layer_id()));

        // Set some state on the pending layer, make sure it is not clobbered
        // by a sync from the active layer.  This could happen because if the
        // pending layer has not been post-commit initialized it will attempt
        // to sync from the active layer.
        float raster_page_scale = 10.f * raw_pending_layer->raster_page_scale();
        raw_pending_layer->set_raster_page_scale(raster_page_scale);

        host_impl()->ActivateSyncTree();

        FakePictureLayerImpl* raw_active_layer = static_cast<FakePictureLayerImpl*>(
            host_impl()->active_tree()->LayerById(layer_id()));

        EXPECT_EQ(0u, raw_active_layer->num_tilings());
        EXPECT_EQ(raster_page_scale, raw_active_layer->raster_page_scale());
    }

    TEST_F(PictureLayerImplTest, ShareTilesOnNextFrame)
    {
        gfx::Size layer_bounds(1500, 1500);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(pending_raster_source);

        PictureLayerTiling* tiling = pending_layer()->HighResTiling();
        gfx::Rect first_invalidate = tiling->TilingDataForTesting().TileBounds(0, 0);
        first_invalidate.Inset(tiling->TilingDataForTesting().border_texels(),
            tiling->TilingDataForTesting().border_texels());
        gfx::Rect second_invalidate = tiling->TilingDataForTesting().TileBounds(1, 1);
        second_invalidate.Inset(tiling->TilingDataForTesting().border_texels(),
            tiling->TilingDataForTesting().border_texels());

        ActivateTree();

        // Make a pending tree with an invalidated raster tile 0,0.
        SetupPendingTreeWithInvalidation(pending_raster_source, first_invalidate);

        // Activate and make a pending tree with an invalidated raster tile 1,1.
        ActivateTree();

        SetupPendingTreeWithInvalidation(pending_raster_source, second_invalidate);

        PictureLayerTiling* pending_tiling = pending_layer()->tilings()->tiling_at(0);
        PictureLayerTiling* active_tiling = active_layer()->tilings()->tiling_at(0);

        // Tile 0,0 not exist on pending, but tile 1,1 should.
        EXPECT_TRUE(active_tiling->TileAt(0, 0));
        EXPECT_TRUE(active_tiling->TileAt(1, 0));
        EXPECT_TRUE(active_tiling->TileAt(0, 1));
        EXPECT_FALSE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 0));
        EXPECT_FALSE(pending_tiling->TileAt(0, 1));
        EXPECT_NE(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
        EXPECT_TRUE(active_tiling->TileAt(1, 1));
        EXPECT_TRUE(pending_tiling->TileAt(1, 1));

        // Drop the tiles on the active tree and recreate them.
        active_layer()->tilings()->UpdateTilePriorities(gfx::Rect(), 1.f, 1.0,
            Occlusion(), true);
        EXPECT_TRUE(active_tiling->AllTilesForTesting().empty());
        active_tiling->CreateAllTilesForTesting();

        // Tile 0,0 not exist on pending, but tile 1,1 should.
        EXPECT_TRUE(active_tiling->TileAt(0, 0));
        EXPECT_TRUE(active_tiling->TileAt(1, 0));
        EXPECT_TRUE(active_tiling->TileAt(0, 1));
        EXPECT_FALSE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 0));
        EXPECT_FALSE(pending_tiling->TileAt(0, 1));
        EXPECT_NE(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1));
        EXPECT_TRUE(active_tiling->TileAt(1, 1));
        EXPECT_TRUE(pending_tiling->TileAt(1, 1));
    }

    TEST_F(PictureLayerImplTest, PendingHasNoTilesWithNoInvalidation)
    {
        SetupDefaultTrees(gfx::Size(1500, 1500));

        EXPECT_GE(active_layer()->num_tilings(), 1u);
        EXPECT_GE(pending_layer()->num_tilings(), 1u);

        // No invalidation.
        PictureLayerTiling* active_tiling = active_layer()->tilings()->tiling_at(0);
        PictureLayerTiling* pending_tiling = pending_layer()->tilings()->tiling_at(0);
        ASSERT_TRUE(active_tiling);
        ASSERT_TRUE(pending_tiling);

        EXPECT_TRUE(active_tiling->TileAt(0, 0));
        EXPECT_TRUE(active_tiling->TileAt(1, 0));
        EXPECT_TRUE(active_tiling->TileAt(0, 1));
        EXPECT_TRUE(active_tiling->TileAt(1, 1));

        EXPECT_FALSE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 0));
        EXPECT_FALSE(pending_tiling->TileAt(0, 1));
        EXPECT_FALSE(pending_tiling->TileAt(1, 1));
    }

    TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTiles)
    {
        gfx::Size layer_bounds(1500, 1500);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupTreesWithInvalidation(pending_raster_source, active_raster_source,
            gfx::Rect(1, 1));
        // Activate the invalidation.
        ActivateTree();
        // Make another pending tree without any invalidation in it.
        scoped_refptr<FakeRasterSource> pending_raster_source2 = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(pending_raster_source2);

        EXPECT_GE(active_layer()->num_tilings(), 1u);
        EXPECT_GE(pending_layer()->num_tilings(), 1u);

        // The active tree invalidation was handled by the active tiles.
        PictureLayerTiling* active_tiling = active_layer()->tilings()->tiling_at(0);
        PictureLayerTiling* pending_tiling = pending_layer()->tilings()->tiling_at(0);
        ASSERT_TRUE(active_tiling);
        ASSERT_TRUE(pending_tiling);

        EXPECT_TRUE(active_tiling->TileAt(0, 0));
        EXPECT_TRUE(active_tiling->TileAt(1, 0));
        EXPECT_TRUE(active_tiling->TileAt(0, 1));
        EXPECT_TRUE(active_tiling->TileAt(1, 1));

        EXPECT_FALSE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 0));
        EXPECT_FALSE(pending_tiling->TileAt(0, 1));
        EXPECT_FALSE(pending_tiling->TileAt(1, 1));
    }

    TEST_F(PictureLayerImplTest, RecreateInvalidPendingTreeTiles)
    {
        // Set some invalidation on the pending tree. We should replace raster tiles
        // that touch this.
        SetupDefaultTreesWithInvalidation(gfx::Size(1500, 1500), gfx::Rect(1, 1));

        EXPECT_GE(active_layer()->num_tilings(), 1u);
        EXPECT_GE(pending_layer()->num_tilings(), 1u);

        // The pending tree invalidation creates tiles on the pending tree.
        PictureLayerTiling* active_tiling = active_layer()->tilings()->tiling_at(0);
        PictureLayerTiling* pending_tiling = pending_layer()->tilings()->tiling_at(0);
        ASSERT_TRUE(active_tiling);
        ASSERT_TRUE(pending_tiling);

        EXPECT_TRUE(active_tiling->TileAt(0, 0));
        EXPECT_TRUE(active_tiling->TileAt(1, 0));
        EXPECT_TRUE(active_tiling->TileAt(0, 1));
        EXPECT_TRUE(active_tiling->TileAt(1, 1));

        EXPECT_TRUE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 0));
        EXPECT_FALSE(pending_tiling->TileAt(0, 1));
        EXPECT_FALSE(pending_tiling->TileAt(1, 1));

        EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0));
    }

    TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size layer_bounds(10, 10);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupTrees(pending_raster_source, active_raster_source);

        EXPECT_TRUE(pending_layer()->tilings()->FindTilingWithScaleKey(1.f));
        EXPECT_TRUE(active_layer()->tilings()->FindTilingWithScaleKey(1.f));

        // Gpu rasterization is disabled by default.
        EXPECT_FALSE(host_impl()->use_gpu_rasterization());
        EXPECT_EQ(0u, pending_layer()->release_tile_resources_count());
        EXPECT_EQ(0u, active_layer()->release_tile_resources_count());
        EXPECT_EQ(0u, pending_layer()->release_resources_count());
        EXPECT_EQ(0u, active_layer()->release_resources_count());
        // Toggling the gpu rasterization clears all tilings on both trees.
        host_impl()->SetHasGpuRasterizationTrigger(true);
        host_impl()->SetContentIsSuitableForGpuRasterization(true);
        host_impl()->CommitComplete();
        EXPECT_EQ(1u, pending_layer()->release_tile_resources_count());
        EXPECT_EQ(1u, active_layer()->release_tile_resources_count());
        EXPECT_EQ(1u, pending_layer()->release_resources_count());
        EXPECT_EQ(1u, active_layer()->release_resources_count());

        // But the pending layer gets a tiling back, and can activate it.
        EXPECT_TRUE(pending_layer()->tilings()->FindTilingWithScaleKey(1.f));
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());

        ActivateTree();
        EXPECT_TRUE(active_layer()->tilings()->FindTilingWithScaleKey(1.f));

        SetupPendingTree(pending_raster_source);
        EXPECT_TRUE(pending_layer()->tilings()->FindTilingWithScaleKey(1.f));

        // Toggling the gpu rasterization clears all tilings on both trees.
        EXPECT_TRUE(host_impl()->use_gpu_rasterization());
        host_impl()->SetHasGpuRasterizationTrigger(false);
        host_impl()->CommitComplete();
        EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
            host_impl()->gpu_rasterization_status());
        EXPECT_EQ(2u, pending_layer()->release_tile_resources_count());
        EXPECT_EQ(2u, active_layer()->release_tile_resources_count());
        EXPECT_EQ(2u, pending_layer()->release_resources_count());
        EXPECT_EQ(2u, active_layer()->release_resources_count());

        host_impl()->SetHasGpuRasterizationTrigger(true);
        host_impl()->SetContentIsSuitableForGpuRasterization(false);
        host_impl()->CommitComplete();
        EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
            host_impl()->gpu_rasterization_status());
    }

    TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink)
    {
        // Put 0.5 as high res.
        SetInitialDeviceScaleFactor(0.5f);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(gfx::Size(10, 10));
        SetupPendingTree(pending_raster_source);

        // Sanity checks.
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_TRUE(pending_layer()->tilings()->FindTilingWithScaleKey(0.5f));

        ActivateTree();

        // Now, set the bounds to be 1x1, so that minimum contents scale becomes 1.
        pending_raster_source = FakeRasterSource::CreateFilled(gfx::Size(1, 1));
        SetupPendingTree(pending_raster_source);

        // Another sanity check.
        EXPECT_EQ(1.f, pending_layer()->MinimumContentsScale());

        // Since the MinContentsScale is 1, the 0.5 tiling should have been replaced
        // by a 1.0 tiling during the UDP in SetupPendingTree.
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
        PictureLayerTiling* tiling = pending_layer()->tilings()->FindTilingWithScaleKey(1.0f);
        ASSERT_TRUE(tiling);
        EXPECT_EQ(HIGH_RESOLUTION, tiling->resolution());
    }

    TEST_F(PictureLayerImplTest, LowResTilingWithoutGpuRasterization)
    {
        gfx::Size default_tile_size(host_impl()->settings().default_tile_size);
        gfx::Size layer_bounds(default_tile_size.width() * 4,
            default_tile_size.height() * 4);

        host_impl()->SetHasGpuRasterizationTrigger(false);

        SetupDefaultTrees(layer_bounds);
        EXPECT_FALSE(host_impl()->use_gpu_rasterization());
        // Should have only a high-res tiling.
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
        ActivateTree();
        // Should add a high and a low res for active tree.
        EXPECT_EQ(2u, active_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization)
    {
        gfx::Size default_tile_size(host_impl()->settings().default_tile_size);
        gfx::Size layer_bounds(default_tile_size.width() * 4,
            default_tile_size.height() * 4);

        host_impl()->SetHasGpuRasterizationTrigger(true);
        host_impl()->SetContentIsSuitableForGpuRasterization(true);
        host_impl()->CommitComplete();

        SetupDefaultTrees(layer_bounds);
        EXPECT_TRUE(host_impl()->use_gpu_rasterization());
        // Should only have the high-res tiling.
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
        ActivateTree();
        // Should only have the high-res tiling.
        EXPECT_EQ(1u, active_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, RequiredTilesWithGpuRasterization)
    {
        host_impl()->SetHasGpuRasterizationTrigger(true);
        host_impl()->SetContentIsSuitableForGpuRasterization(true);
        host_impl()->CommitComplete();

        gfx::Size viewport_size(1000, 1000);
        host_impl()->SetViewportSize(viewport_size);

        gfx::Size layer_bounds(4000, 4000);
        SetupDefaultTrees(layer_bounds);
        EXPECT_TRUE(host_impl()->use_gpu_rasterization());

        // Should only have the high-res tiling.
        EXPECT_EQ(1u, active_layer()->tilings()->num_tilings());

        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();

        // High res tiling should have 64 tiles (4x16 tile grid).
        EXPECT_EQ(64u, active_layer()->HighResTiling()->AllTilesForTesting().size());

        // Visible viewport should be covered by 4 tiles.  No other
        // tiles should be required for activation.
        EXPECT_EQ(4u, NumberOfTilesRequired(active_layer()->HighResTiling()));
    }

    TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent)
    {
        // Set up layers with tilings.
        SetupDefaultTrees(gfx::Size(10, 10));
        SetContentsScaleOnBothLayers(1.f, 1.f, 1.f, 1.f, 0.f, false);
        pending_layer()->PushPropertiesTo(active_layer());
        EXPECT_TRUE(pending_layer()->DrawsContent());
        EXPECT_TRUE(pending_layer()->CanHaveTilings());
        EXPECT_GE(pending_layer()->num_tilings(), 0u);
        EXPECT_GE(active_layer()->num_tilings(), 0u);

        // Set content to false, which should make CanHaveTilings return false.
        pending_layer()->SetDrawsContent(false);
        EXPECT_FALSE(pending_layer()->DrawsContent());
        EXPECT_FALSE(pending_layer()->CanHaveTilings());

        // No tilings should be pushed to active layer.
        pending_layer()->PushPropertiesTo(active_layer());
        EXPECT_EQ(0u, active_layer()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, FirstTilingDuringPinch)
    {
        SetupDefaultTrees(gfx::Size(10, 10));

        // We start with a tiling at scale 1.
        EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale());

        // When we page scale up by 2.3, we get a new tiling that is a power of 2, in
        // this case 4.
        host_impl()->PinchGestureBegin();
        float high_res_scale = 2.3f;
        SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, 0.f,
            false);
        EXPECT_EQ(4.f, pending_layer()->HighResTiling()->contents_scale());
    }

    TEST_F(PictureLayerImplTest, PinchingTooSmall)
    {
        SetupDefaultTrees(gfx::Size(10, 10));

        // We start with a tiling at scale 1.
        EXPECT_EQ(1.f, pending_layer()->HighResTiling()->contents_scale());

        host_impl()->PinchGestureBegin();
        float high_res_scale = 0.0001f;
        EXPECT_LT(high_res_scale, pending_layer()->MinimumContentsScale());

        SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, 0.f,
            false);
        EXPECT_FLOAT_EQ(pending_layer()->MinimumContentsScale(),
            pending_layer()->HighResTiling()->contents_scale());
    }

    TEST_F(PictureLayerImplTest, PinchingTooSmallWithContentsScale)
    {
        SetupDefaultTrees(gfx::Size(10, 10));

        ResetTilingsAndRasterScales();

        float contents_scale = 0.15f;
        SetContentsScaleOnBothLayers(contents_scale, 1.f, 1.f, 1.f, 0.f, false);

        ASSERT_GE(pending_layer()->num_tilings(), 0u);
        EXPECT_FLOAT_EQ(contents_scale,
            pending_layer()->HighResTiling()->contents_scale());

        host_impl()->PinchGestureBegin();

        float page_scale = 0.0001f;
        EXPECT_LT(page_scale * contents_scale,
            pending_layer()->MinimumContentsScale());

        SetContentsScaleOnBothLayers(contents_scale * page_scale, 1.f, page_scale,
            1.f, 0.f, false);
        ASSERT_GE(pending_layer()->num_tilings(), 0u);
        EXPECT_FLOAT_EQ(pending_layer()->MinimumContentsScale(),
            pending_layer()->HighResTiling()->contents_scale());
    }

    TEST_F(PictureLayerImplTest, ConsiderAnimationStartScaleForRasterScale)
    {
        gfx::Size viewport_size(1000, 1000);
        host_impl()->SetViewportSize(viewport_size);

        gfx::Size layer_bounds(100, 100);
        SetupDefaultTrees(layer_bounds);

        float contents_scale = 2.f;
        float device_scale = 1.f;
        float page_scale = 1.f;
        float maximum_animation_scale = 3.f;
        float starting_animation_scale = 1.f;
        bool animating_transform = true;

        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);

        // Maximum animation scale is greater than starting animation scale
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);

        animating_transform = false;

        // Once we stop animating, a new high-res tiling should be created.
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);

        // Starting animation scale greater than maximum animation scale
        // Bounds at starting scale within the viewport
        animating_transform = true;
        starting_animation_scale = 5.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 5.f);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;
        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);

        // Starting Animation scale greater than maximum animation scale
        // Bounds at starting scale outisde the viewport
        animating_transform = true;
        starting_animation_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
    }

    TEST_F(PictureLayerImplTest, HighResTilingDuringAnimation)
    {
        gfx::Size viewport_size(1000, 1000);
        host_impl()->SetViewportSize(viewport_size);

        gfx::Size layer_bounds(100, 100);
        SetupDefaultTrees(layer_bounds);

        float contents_scale = 1.f;
        float device_scale = 1.f;
        float page_scale = 1.f;
        float maximum_animation_scale = 1.f;
        float starting_animation_scale = 0.f;
        bool animating_transform = false;

        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f);

        // Starting an animation should cause tiling resolution to get set to the
        // maximum animation scale factor.
        animating_transform = true;
        maximum_animation_scale = 3.f;
        contents_scale = 2.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);

        // Further changes to scale during the animation should not cause a new
        // high-res tiling to get created.
        contents_scale = 4.f;
        maximum_animation_scale = 5.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);

        // When animating with an unknown maximum animation scale factor, a new
        // high-res tiling should be created at a source scale of 1.
        animating_transform = true;
        contents_scale = 2.f;
        maximum_animation_scale = 0.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale);

        // Further changes to scale during the animation should not cause a new
        // high-res tiling to get created.
        contents_scale = 3.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;
        contents_scale = 4.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 4.f);

        // When animating with a maxmium animation scale factor that is so large
        // that the layer grows larger than the viewport at this scale, a new
        // high-res tiling should get created at a source scale of 1, not at its
        // maximum scale.
        animating_transform = true;
        contents_scale = 2.f;
        maximum_animation_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), page_scale * device_scale);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;
        contents_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);

        // When animating with a maxmium animation scale factor that is so large
        // that the layer grows larger than the viewport at this scale, and where
        // the intial source scale is < 1, a new high-res tiling should get created
        // at source scale 1.
        animating_transform = true;
        contents_scale = 0.1f;
        maximum_animation_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;
        contents_scale = 12.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 12.f);

        // When animating toward a smaller scale, but that is still so large that the
        // layer grows larger than the viewport at this scale, a new high-res tiling
        // should get created at source scale 1.
        animating_transform = true;
        contents_scale = 11.f;
        maximum_animation_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), device_scale * page_scale);

        // Once we stop animating, a new high-res tiling should be created.
        animating_transform = false;
        contents_scale = 11.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 11.f);
    }

    TEST_F(PictureLayerImplTest, TilingSetRasterQueue)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        host_impl()->SetViewportSize(gfx::Size(500, 500));

        gfx::Size layer_bounds(1000, 1000);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(pending_raster_source);
        EXPECT_EQ(1u, pending_layer()->num_tilings());

        std::set<Tile*> unique_tiles;
        bool reached_prepaint = false;
        int non_ideal_tile_count = 0u;
        int low_res_tile_count = 0u;
        int high_res_tile_count = 0u;
        int high_res_now_tiles = 0u;
        std::unique_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            TilePriority priority = prioritized_tile.priority();

            EXPECT_TRUE(prioritized_tile.tile());

            // Non-high res tiles only get visible tiles. Also, prepaint should only
            // come at the end of the iteration.
            if (priority.resolution != HIGH_RESOLUTION) {
                EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
            } else if (reached_prepaint) {
                EXPECT_NE(TilePriority::NOW, priority.priority_bin);
            } else {
                reached_prepaint = priority.priority_bin != TilePriority::NOW;
                if (!reached_prepaint)
                    ++high_res_now_tiles;
            }

            non_ideal_tile_count += priority.resolution == NON_IDEAL_RESOLUTION;
            low_res_tile_count += priority.resolution == LOW_RESOLUTION;
            high_res_tile_count += priority.resolution == HIGH_RESOLUTION;

            unique_tiles.insert(prioritized_tile.tile());
            queue->Pop();
        }

        EXPECT_TRUE(reached_prepaint);
        EXPECT_EQ(0, non_ideal_tile_count);
        EXPECT_EQ(0, low_res_tile_count);

        // With layer size being 1000x1000 and default tile size 256x256, we expect to
        // see 4 now tiles out of 16 total high res tiles.
        EXPECT_EQ(16, high_res_tile_count);
        EXPECT_EQ(4, high_res_now_tiles);
        EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count,
            static_cast<int>(unique_tiles.size()));

        std::unique_ptr<TilingSetRasterQueueRequired> required_queue(
            new TilingSetRasterQueueRequired(
                pending_layer()->picture_layer_tiling_set(),
                RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW));
        EXPECT_TRUE(required_queue->IsEmpty());

        required_queue.reset(new TilingSetRasterQueueRequired(
            pending_layer()->picture_layer_tiling_set(),
            RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
        EXPECT_FALSE(required_queue->IsEmpty());
        int required_for_activation_count = 0;
        while (!required_queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = required_queue->Top();
            EXPECT_TRUE(prioritized_tile.tile()->required_for_activation());
            EXPECT_FALSE(prioritized_tile.tile()->draw_info().IsReadyToDraw());
            ++required_for_activation_count;
            required_queue->Pop();
        }

        // All of the high res tiles should be required for activation, since there is
        // no active twin.
        EXPECT_EQ(high_res_now_tiles, required_for_activation_count);

        // No NOW tiles.
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        pending_layer()->draw_properties().visible_layer_rect = gfx::Rect(1100, 1100, 500, 500);
        pending_layer()->UpdateTiles();

        unique_tiles.clear();
        high_res_tile_count = 0u;
        queue.reset(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            TilePriority priority = prioritized_tile.priority();

            EXPECT_TRUE(prioritized_tile.tile());

            // Non-high res tiles only get visible tiles.
            EXPECT_EQ(HIGH_RESOLUTION, priority.resolution);
            EXPECT_NE(TilePriority::NOW, priority.priority_bin);

            high_res_tile_count += priority.resolution == HIGH_RESOLUTION;

            unique_tiles.insert(prioritized_tile.tile());
            queue->Pop();
        }

        EXPECT_EQ(16, high_res_tile_count);
        EXPECT_EQ(high_res_tile_count, static_cast<int>(unique_tiles.size()));

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));

        pending_layer()->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 500, 500);
        pending_layer()->UpdateTiles();

        std::vector<Tile*> high_res_tiles = pending_layer()->HighResTiling()->AllTilesForTesting();
        for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin();
             tile_it != high_res_tiles.end();
             ++tile_it) {
            Tile* tile = *tile_it;
            TileDrawInfo& draw_info = tile->draw_info();
            draw_info.SetSolidColorForTesting(SK_ColorRED);
        }

        queue.reset(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), true));
        EXPECT_TRUE(queue->IsEmpty());
    }

    TEST_F(PictureLayerImplTest, TilingSetRasterQueueActiveTree)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        host_impl()->SetViewportSize(gfx::Size(500, 500));

        gfx::Size layer_bounds(1000, 1000);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTree(pending_raster_source);
        ActivateTree();
        EXPECT_EQ(2u, active_layer()->num_tilings());

        std::unique_ptr<TilingSetRasterQueueRequired> queue(
            new TilingSetRasterQueueRequired(
                active_layer()->picture_layer_tiling_set(),
                RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW));
        EXPECT_FALSE(queue->IsEmpty());
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            EXPECT_TRUE(prioritized_tile.tile()->required_for_draw());
            EXPECT_FALSE(prioritized_tile.tile()->draw_info().IsReadyToDraw());
            queue->Pop();
        }

        queue.reset(new TilingSetRasterQueueRequired(
            active_layer()->picture_layer_tiling_set(),
            RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
        EXPECT_TRUE(queue->IsEmpty());
    }

    TEST_F(PictureLayerImplTest, TilingSetRasterQueueRequiredNoHighRes)
    {
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilledSolidColor(gfx::Size(1024, 1024));

        SetupPendingTree(pending_raster_source);
        EXPECT_FALSE(
            pending_layer()->picture_layer_tiling_set()->FindTilingWithResolution(
                HIGH_RESOLUTION));

        std::unique_ptr<TilingSetRasterQueueRequired> queue(
            new TilingSetRasterQueueRequired(
                pending_layer()->picture_layer_tiling_set(),
                RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
        EXPECT_TRUE(queue->IsEmpty());
    }

    TEST_F(PictureLayerImplTest, TilingSetEvictionQueue)
    {
        gfx::Size layer_bounds(1000, 1000);
        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;

        host_impl()->SetViewportSize(gfx::Size(500, 500));

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        // TODO(vmpstr): Add a test with tilings other than high res on the active
        // tree (crbug.com/519607).
        SetupPendingTree(pending_raster_source);
        EXPECT_EQ(1u, pending_layer()->num_tilings());

        std::vector<Tile*> all_tiles;
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            all_tiles.insert(all_tiles.end(), tiles.begin(), tiles.end());
        }

        std::set<Tile*> all_tiles_set(all_tiles.begin(), all_tiles.end());

        bool mark_required = false;
        size_t number_of_marked_tiles = 0u;
        size_t number_of_unmarked_tiles = 0u;
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            for (PictureLayerTiling::CoverageIterator iter(
                     tiling, 1.f, pending_layer()->visible_layer_rect());
                 iter; ++iter) {
                if (mark_required) {
                    number_of_marked_tiles++;
                    iter->set_required_for_activation(true);
                } else {
                    number_of_unmarked_tiles++;
                }
                mark_required = !mark_required;
            }
        }

        // Sanity checks.
        EXPECT_EQ(16u, all_tiles.size());
        EXPECT_EQ(16u, all_tiles_set.size());
        EXPECT_GT(number_of_marked_tiles, 1u);
        EXPECT_GT(number_of_unmarked_tiles, 1u);

        // Tiles don't have resources yet.
        std::unique_ptr<TilingSetEvictionQueue> queue(
            new TilingSetEvictionQueue(pending_layer()->picture_layer_tiling_set()));
        EXPECT_TRUE(queue->IsEmpty());

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            all_tiles);

        std::set<Tile*> unique_tiles;
        float expected_scales[] = { low_res_factor, 1.f };
        size_t scale_index = 0;
        bool reached_visible = false;
        PrioritizedTile last_tile;
        size_t distance_decreasing = 0;
        size_t distance_increasing = 0;
        queue.reset(
            new TilingSetEvictionQueue(pending_layer()->picture_layer_tiling_set()));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            Tile* tile = prioritized_tile.tile();
            if (!last_tile.tile())
                last_tile = prioritized_tile;

            EXPECT_TRUE(tile);

            TilePriority priority = prioritized_tile.priority();

            if (priority.priority_bin == TilePriority::NOW) {
                reached_visible = true;
                last_tile = prioritized_tile;
                break;
            }

            EXPECT_FALSE(tile->required_for_activation());

            while (std::abs(tile->contents_scale() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) {
                ++scale_index;
                ASSERT_LT(scale_index, arraysize(expected_scales));
            }

            EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]);
            unique_tiles.insert(tile);

            if (tile->required_for_activation() == last_tile.tile()->required_for_activation() && std::abs(tile->contents_scale() - last_tile.tile()->contents_scale()) < std::numeric_limits<float>::epsilon()) {
                if (priority.distance_to_visible <= last_tile.priority().distance_to_visible)
                    ++distance_decreasing;
                else
                    ++distance_increasing;
            }

            last_tile = prioritized_tile;
            queue->Pop();
        }

        // 4 high res tiles are inside the viewport, the rest are evicted.
        EXPECT_TRUE(reached_visible);
        EXPECT_EQ(12u, unique_tiles.size());
        EXPECT_EQ(1u, distance_increasing);
        EXPECT_EQ(11u, distance_decreasing);

        scale_index = 0;
        bool reached_required = false;
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            Tile* tile = prioritized_tile.tile();
            EXPECT_TRUE(tile);

            TilePriority priority = prioritized_tile.priority();
            EXPECT_EQ(TilePriority::NOW, priority.priority_bin);

            if (reached_required) {
                EXPECT_TRUE(tile->required_for_activation());
            } else if (tile->required_for_activation()) {
                reached_required = true;
                scale_index = 0;
            }

            while (std::abs(tile->contents_scale() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) {
                ++scale_index;
                ASSERT_LT(scale_index, arraysize(expected_scales));
            }

            EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]);
            unique_tiles.insert(tile);
            queue->Pop();
        }

        EXPECT_TRUE(reached_required);
        EXPECT_EQ(all_tiles_set.size(), unique_tiles.size());
    }

    TEST_F(PictureLayerImplTest, Occlusion)
    {
        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(1000, 1000);

        LayerTestCommon::LayerImplTest impl;
        host_impl()->SetViewportSize(viewport_size);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        std::vector<Tile*> tiles = active_layer()->HighResTiling()->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);

        {
            SCOPED_TRACE("No occlusion");
            gfx::Rect occluded;
            impl.AppendQuadsWithOcclusion(active_layer(), occluded);

            LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
                gfx::Rect(layer_bounds));
            EXPECT_EQ(100u, impl.quad_list().size());
        }

        {
            SCOPED_TRACE("Full occlusion");
            gfx::Rect occluded(active_layer()->visible_layer_rect());
            impl.AppendQuadsWithOcclusion(active_layer(), occluded);

            LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
            EXPECT_EQ(impl.quad_list().size(), 0u);
        }

        {
            SCOPED_TRACE("Partial occlusion");
            gfx::Rect occluded(150, 0, 200, 1000);
            impl.AppendQuadsWithOcclusion(active_layer(), occluded);

            size_t partially_occluded_count = 0;
            LayerTestCommon::VerifyQuadsAreOccluded(
                impl.quad_list(), occluded, &partially_occluded_count);
            // The layer outputs one quad, which is partially occluded.
            EXPECT_EQ(100u - 10u, impl.quad_list().size());
            EXPECT_EQ(10u + 10u, partially_occluded_count);
        }
    }

    TEST_F(PictureLayerImplTest, RasterScaleChangeWithoutAnimation)
    {
        gfx::Size tile_size(host_impl()->settings().default_tile_size);
        SetupDefaultTrees(tile_size);

        ResetTilingsAndRasterScales();

        float contents_scale = 2.f;
        float device_scale = 1.f;
        float page_scale = 1.f;
        float maximum_animation_scale = 1.f;
        float starting_animation_scale = 0.f;
        bool animating_transform = false;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f);

        // Changing the source scale without being in an animation will cause
        // the layer to change scale.
        contents_scale = 3.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);

        contents_scale = 0.5f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f);

        // However, if the layer has a will-change property, then the raster scale
        // will get fixed at the last value.
        active_layer()->SetHasWillChangeTransformHint(true);
        pending_layer()->SetHasWillChangeTransformHint(true);

        contents_scale = 3.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f);

        // Further changes to the source scale will no longer be reflected in the
        // contents scale.
        contents_scale = 1.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 0.5f);

        // Disabling the will-change hint will once again make the raster scale update
        // with the ideal scale.
        active_layer()->SetHasWillChangeTransformHint(false);
        pending_layer()->SetHasWillChangeTransformHint(false);

        contents_scale = 3.f;

        SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
            maximum_animation_scale,
            starting_animation_scale, animating_transform);
        EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 3.f);
    }

    TEST_F(PictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate)
    {
        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(1000, 1000);

        // Make sure pending tree has tiles.
        gfx::Rect invalidation(gfx::Point(50, 50), tile_size);
        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation);

        // All pending layer tiles required are not ready.
        EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToActivate());

        // Initialize all low-res tiles.
        EXPECT_FALSE(pending_layer()->LowResTiling());
        pending_layer()->SetAllTilesReadyInTiling(active_layer()->LowResTiling());

        // Low-res tiles should not be enough.
        EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToActivate());

        // Initialize remaining tiles.
        pending_layer()->SetAllTilesReady();
        active_layer()->SetAllTilesReady();

        EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate());
    }

    TEST_F(PictureLayerImplTest, HighResReadyToDrawEnoughToActivate)
    {
        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(1000, 1000);

        // Make sure pending tree has tiles.
        gfx::Rect invalidation(gfx::Point(50, 50), tile_size);
        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation);

        // All pending layer tiles required are not ready.
        EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToActivate());

        // Initialize all high-res tiles.
        pending_layer()->SetAllTilesReadyInTiling(pending_layer()->HighResTiling());
        active_layer()->SetAllTilesReadyInTiling(active_layer()->HighResTiling());

        // High-res tiles should be enough, since they cover everything visible.
        EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate());
    }

    TEST_F(PictureLayerImplTest, ActiveHighResReadyNotEnoughToActivate)
    {
        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(1000, 1000);

        // Make sure pending tree has tiles.
        gfx::Rect invalidation(gfx::Point(50, 50), tile_size);
        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation);

        // Initialize all high-res tiles in the active layer.
        active_layer()->SetAllTilesReadyInTiling(active_layer()->HighResTiling());

        // The pending high-res tiles are not ready, so we cannot activate.
        EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToActivate());

        // When the pending high-res tiles are ready, we can activate.
        pending_layer()->SetAllTilesReadyInTiling(pending_layer()->HighResTiling());
        EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate());
    }

    TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        ResetTilingsAndRasterScales();

        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            6.f, // ideal contents scale
            3.f, // device scale
            2.f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the page scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            6.6f, // ideal contents scale
            3.f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.6f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            7.26f, // ideal contents scale
            3.3f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, but end up at the same total scale
        // factor somehow, then we don't get new tilings.
        SetupDrawPropertiesAndUpdateTiles(active_layer(),
            7.26f, // ideal contents scale
            2.2f, // device scale
            3.3f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(3u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
    }

    TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        ResetTilingsAndRasterScales();

        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            6.f, // ideal contents scale
            3.f, // device scale
            2.f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the page scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            6.6f, // ideal contents scale
            3.f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(6.6f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, then we should get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            7.26f, // ideal contents scale
            3.3f, // device scale
            2.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());

        // If we change the device scale factor, but end up at the same total scale
        // factor somehow, then we don't get new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            7.26f, // ideal contents scale
            2.2f, // device scale
            3.3f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        ASSERT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(7.26f,
            pending_layer()->tilings()->tiling_at(0)->contents_scale());
    }

    TEST_F(NoLowResPictureLayerImplTest, AllHighResRequiredEvenIfNotChanged)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region());

        Tile* some_active_tile = active_layer()->HighResTiling()->AllTilesForTesting()[0];
        EXPECT_FALSE(some_active_tile->draw_info().IsReadyToDraw());

        // Since there is no invalidation, pending tree should have no tiles.
        EXPECT_TRUE(pending_layer()->HighResTiling()->AllTilesForTesting().empty());
        if (host_impl()->settings().create_low_res_tiling)
            EXPECT_TRUE(pending_layer()->LowResTiling()->AllTilesForTesting().empty());

        active_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        if (host_impl()->settings().create_low_res_tiling)
            active_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        AssertAllTilesRequired(active_layer()->HighResTiling());
        if (host_impl()->settings().create_low_res_tiling)
            AssertNoTilesRequired(active_layer()->LowResTiling());
    }

    TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles)
    {
        gfx::Size layer_bounds(400, 400);
        gfx::Size tile_size(100, 100);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        // This raster source will create tilings, but has no recordings so will not
        // create any tiles.  This is attempting to simulate scrolling past the end of
        // recorded content on the active layer, where the recordings are so far away
        // that no tiles are created.
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds, gfx::Rect());

        SetupTreesWithFixedTileSize(pending_raster_source, active_raster_source,
            tile_size, Region());

        // Active layer has tilings, but no tiles due to missing recordings.
        EXPECT_TRUE(active_layer()->CanHaveTilings());
        EXPECT_EQ(active_layer()->tilings()->num_tilings(),
            host_impl()->settings().create_low_res_tiling ? 2u : 1u);
        EXPECT_EQ(active_layer()->HighResTiling()->AllTilesForTesting().size(), 0u);

        // Since the active layer has no tiles at all, the pending layer doesn't
        // need content in order to activate.
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();
        if (host_impl()->settings().create_low_res_tiling)
            pending_layer()->LowResTiling()->UpdateAllRequiredStateForTesting();

        AssertNoTilesRequired(pending_layer()->HighResTiling());
        if (host_impl()->settings().create_low_res_tiling)
            AssertNoTilesRequired(pending_layer()->LowResTiling());
    }

    TEST_F(NoLowResPictureLayerImplTest, CleanUpTilings)
    {
        gfx::Size layer_bounds(1300, 1900);
        std::vector<PictureLayerTiling*> used_tilings;
        SetupDefaultTrees(layer_bounds);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        EXPECT_LT(low_res_factor, 1.f);

        float device_scale = 1.7f;
        float page_scale = 3.2f;
        float scale = 1.f;

        active_layer()->SetHasWillChangeTransformHint(true);
        ResetTilingsAndRasterScales();

        SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, 0.f,
            false);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());

        // Ensure UpdateTiles won't remove any tilings. Note this is unrelated to
        // |used_tilings| variable, and it's here only to ensure that active_layer()
        // won't remove tilings before the test has a chance to verify behavior.
        active_layer()->MarkAllTilingsUsed();

        // We only have ideal tilings, so they aren't removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());

        host_impl()->PinchGestureBegin();

        // Changing the ideal but not creating new tilings.
        scale *= 1.5f;
        page_scale *= 1.5f;
        SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, 0.f,
            false);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());

        // The tilings are still our target scale, so they aren't removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());

        host_impl()->PinchGestureEnd();

        // Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2.
        scale /= 4.f;
        page_scale /= 4.f;
        SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, 1.f, 0.f, false);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_FLOAT_EQ(1.f,
            active_layer()->tilings()->tiling_at(1)->contents_scale());

        // Ensure UpdateTiles won't remove any tilings.
        active_layer()->MarkAllTilingsUsed();

        // Mark the non-ideal tilings as used. They won't be removed.
        used_tilings.clear();
        used_tilings.push_back(active_layer()->tilings()->tiling_at(1));
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());

        // Now move the ideal scale to 0.5. Our target stays 1.2.
        SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, 1.f, 0.f, false);

        // The high resolution tiling is between target and ideal, so is not
        // removed.  The low res tiling for the old ideal=1.0 scale is removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());

        // Now move the ideal scale to 1.0. Our target stays 1.2.
        SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, 1.f, 0.f, false);

        // All the tilings are between are target and the ideal, so they are not
        // removed.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());

        // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
        SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.1f, device_scale,
            page_scale, 1.f, 0.f, false);

        // Because the pending layer's ideal scale is still 1.0, our tilings fall
        // in the range [1.0,1.2] and are kept.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());

        // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
        // 1.2 still.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.1f, device_scale,
            page_scale, 1.f, 0.f, false);

        // Our 1.0 tiling now falls outside the range between our ideal scale and our
        // target raster scale. But it is in our used tilings set, so nothing is
        // deleted.
        used_tilings.clear();
        used_tilings.push_back(active_layer()->tilings()->tiling_at(1));
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(2u, active_layer()->tilings()->num_tilings());

        // If we remove it from our used tilings set, it is outside the range to keep
        // so it is deleted.
        used_tilings.clear();
        active_layer()->CleanUpTilingsOnActiveLayer(used_tilings);
        ASSERT_EQ(1u, active_layer()->tilings()->num_tilings());
    }

    TEST_F(NoLowResPictureLayerImplTest, ReleaseTileResources)
    {
        gfx::Size layer_bounds(1300, 1900);
        SetupDefaultTrees(layer_bounds);
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
        EXPECT_EQ(1u, active_layer()->tilings()->num_tilings());

        // All tilings should be removed when losing output surface.
        active_layer()->ReleaseTileResources();
        EXPECT_FALSE(active_layer()->tilings());
        active_layer()->RecreateTileResources();
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
        pending_layer()->ReleaseTileResources();
        EXPECT_FALSE(pending_layer()->tilings());
        pending_layer()->RecreateTileResources();
        EXPECT_EQ(0u, pending_layer()->tilings()->num_tilings());

        // This should create new tilings.
        SetupDrawPropertiesAndUpdateTiles(pending_layer(),
            1.3f, // ideal contents scale
            2.7f, // device scale
            3.2f, // page scale
            1.f, // maximum animation scale
            0.f, // starting animation scale
            false);
        EXPECT_EQ(1u, pending_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, SharedQuadStateContainsMaxTilingScale)
    {
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();

        gfx::Size layer_bounds(1000, 2000);
        host_impl()->SetViewportSize(gfx::Size(10000, 20000));
        SetupDefaultTrees(layer_bounds);

        ResetTilingsAndRasterScales();
        SetupDrawPropertiesAndUpdateTiles(active_layer(), 2.5f, 1.f, 1.f, 1.f, 0.f,
            false);

        float max_contents_scale = active_layer()->MaximumTilingContentsScale();
        EXPECT_EQ(2.5f, max_contents_scale);

        gfx::Transform scaled_draw_transform = active_layer()->DrawTransform();
        scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
            SK_MScalar1 / max_contents_scale);

        AppendQuadsData data;
        active_layer()->AppendQuads(render_pass.get(), &data);

        // SharedQuadState should have be of size 1, as we are doing AppenQuad once.
        EXPECT_EQ(1u, render_pass->shared_quad_state_list.size());
        // The quad_to_target_transform should be scaled by the
        // MaximumTilingContentsScale on the layer.
        EXPECT_EQ(scaled_draw_transform.ToString(),
            render_pass->shared_quad_state_list.front()
                ->quad_to_target_transform.ToString());
        // The content_bounds should be scaled by the
        // MaximumTilingContentsScale on the layer.
        EXPECT_EQ(gfx::Size(2500u, 5000u).ToString(),
            render_pass->shared_quad_state_list.front()
                ->quad_layer_bounds.ToString());
        // The visible_layer_rect should be scaled by the
        // MaximumTilingContentsScale on the layer.
        EXPECT_EQ(gfx::Rect(0u, 0u, 2500u, 5000u).ToString(),
            render_pass->shared_quad_state_list.front()
                ->visible_quad_layer_rect.ToString());
    }

    class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest {
    public:
        std::unique_ptr<CompositorFrameSink> CreateCompositorFrameSink() override
        {
            return FakeCompositorFrameSink::Create3d();
        }
    };

    TEST_F(PictureLayerImplTestWithDelegatingRenderer,
        DelegatingRendererWithTileOOM)
    {
        // This test is added for crbug.com/402321, where quad should be produced when
        // raster on demand is not allowed and tile is OOM.
        gfx::Size layer_bounds(1000, 1000);

        // Create tiles.
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(pending_raster_source);
        pending_layer()->SetBounds(layer_bounds);
        ActivateTree();
        bool update_lcd_text = false;
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);
        std::vector<Tile*> tiles = active_layer()->HighResTiling()->AllTilesForTesting();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);

        // Force tiles after max_tiles to be OOM. TileManager uses
        // GlobalStateThatImpactsTilesPriority from LayerTreeHostImpl, and we cannot
        // directly set state to host_impl_, so we set policy that would change the
        // state. We also need to update tree priority separately.
        GlobalStateThatImpactsTilePriority state;
        size_t max_tiles = 1;
        gfx::Size tile_size(host_impl()->settings().default_tile_size);
        size_t memory_limit = max_tiles * 4 * tile_size.width() * tile_size.height();
        size_t resource_limit = max_tiles;
        ManagedMemoryPolicy policy(memory_limit,
            gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
            resource_limit);
        host_impl()->SetMemoryPolicy(policy);
        host_impl()->SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
        host_impl()->PrepareTiles();

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_HARDWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        // Even when OOM, quads should be produced, and should be different material
        // from quads with resource.
        EXPECT_LT(max_tiles, render_pass->quad_list.size());
        EXPECT_EQ(DrawQuad::Material::TILED_CONTENT,
            render_pass->quad_list.front()->material);
        EXPECT_EQ(DrawQuad::Material::SOLID_COLOR,
            render_pass->quad_list.back()->material);
    }

    class OcclusionTrackingPictureLayerImplTest : public PictureLayerImplTest {
    public:
        LayerTreeSettings CreateSettings() override
        {
            LayerTreeSettings settings = PictureLayerImplTest::CreateSettings();
            settings.use_occlusion_for_tile_prioritization = true;
            return settings;
        }

        void VerifyEvictionConsidersOcclusion(FakePictureLayerImpl* layer,
            WhichTree tree,
            size_t expected_occluded_tile_count,
            int source_line)
        {
            size_t occluded_tile_count = 0u;
            PrioritizedTile last_tile;

            std::unique_ptr<TilingSetEvictionQueue> queue(
                new TilingSetEvictionQueue(layer->picture_layer_tiling_set()));
            while (!queue->IsEmpty()) {
                PrioritizedTile prioritized_tile = queue->Top();
                Tile* tile = prioritized_tile.tile();
                if (!last_tile.tile())
                    last_tile = prioritized_tile;

                // The only way we will encounter an occluded tile after an unoccluded
                // tile is if the priorty bin decreased, the tile is required for
                // activation, or the scale changed.
                bool tile_is_occluded = prioritized_tile.is_occluded();
                if (tile_is_occluded) {
                    occluded_tile_count++;

                    bool last_tile_is_occluded = last_tile.is_occluded();
                    if (!last_tile_is_occluded) {
                        TilePriority::PriorityBin tile_priority_bin = prioritized_tile.priority().priority_bin;
                        TilePriority::PriorityBin last_tile_priority_bin = last_tile.priority().priority_bin;

                        EXPECT_TRUE(tile_priority_bin < last_tile_priority_bin || tile->required_for_activation() || tile->contents_scale() != last_tile.tile()->contents_scale())
                            << "line: " << source_line;
                    }
                }
                last_tile = prioritized_tile;
                queue->Pop();
            }
            EXPECT_EQ(expected_occluded_tile_count, occluded_tile_count)
                << "line: " << source_line;
        }
    };

    TEST_F(OcclusionTrackingPictureLayerImplTest,
        OccludedTilesSkippedDuringRasterization)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(500, 500);
        gfx::PointF occluding_layer_position(310.f, 0.f);

        host_impl()->SetViewportSize(viewport_size);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());

        // No occlusion.
        int unoccluded_tile_count = 0;
        std::unique_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            Tile* tile = prioritized_tile.tile();

            // Occluded tiles should not be iterated over.
            EXPECT_FALSE(prioritized_tile.is_occluded());

            // Some tiles may not be visible (i.e. outside the viewport). The rest are
            // visible and at least partially unoccluded, verified by the above expect.
            bool tile_is_visible = tile->content_rect().Intersects(pending_layer()->visible_layer_rect());
            if (tile_is_visible)
                unoccluded_tile_count++;
            queue->Pop();
        }
        EXPECT_EQ(unoccluded_tile_count, 25);

        // Partial occlusion.
        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 1));
        LayerImpl* layer1 = pending_layer()->test_properties()->children[0];
        layer1->SetBounds(layer_bounds);
        layer1->SetDrawsContent(true);
        layer1->SetContentsOpaque(true);
        layer1->SetPosition(occluding_layer_position);

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        unoccluded_tile_count = 0;
        queue.reset(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            Tile* tile = prioritized_tile.tile();

            EXPECT_FALSE(prioritized_tile.is_occluded());

            bool tile_is_visible = tile->content_rect().Intersects(pending_layer()->visible_layer_rect());
            if (tile_is_visible)
                unoccluded_tile_count++;
            queue->Pop();
        }
        EXPECT_EQ(20, unoccluded_tile_count);

        // Full occlusion.
        layer1->SetPosition(gfx::PointF());
        layer1->NoteLayerPropertyChanged();

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        unoccluded_tile_count = 0;
        queue.reset(new TilingSetRasterQueueAll(
            pending_layer()->picture_layer_tiling_set(), false));
        while (!queue->IsEmpty()) {
            PrioritizedTile prioritized_tile = queue->Top();
            Tile* tile = prioritized_tile.tile();

            EXPECT_FALSE(prioritized_tile.is_occluded());

            bool tile_is_visible = tile->content_rect().Intersects(pending_layer()->visible_layer_rect());
            if (tile_is_visible)
                unoccluded_tile_count++;
            queue->Pop();
        }
        EXPECT_EQ(unoccluded_tile_count, 0);
    }

    TEST_F(OcclusionTrackingPictureLayerImplTest,
        OccludedTilesNotMarkedAsRequired)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(500, 500);
        gfx::PointF occluding_layer_position(310.f, 0.f);

        host_impl()->SetViewportSize(viewport_size);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());

        // No occlusion.
        int occluded_tile_count = 0;
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            occluded_tile_count = 0;
            for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f,
                     gfx::Rect(layer_bounds));
                 iter; ++iter) {
                if (!*iter)
                    continue;
                const Tile* tile = *iter;

                // Fully occluded tiles are not required for activation.
                if (prioritized_tiles[tile].is_occluded()) {
                    EXPECT_FALSE(tile->required_for_activation());
                    occluded_tile_count++;
                }
            }
            EXPECT_EQ(occluded_tile_count, 0);
        }

        // Partial occlusion.
        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 1));
        LayerImpl* layer1 = pending_layer()->test_properties()->children[0];
        layer1->SetBounds(layer_bounds);
        layer1->SetDrawsContent(true);
        layer1->SetContentsOpaque(true);
        layer1->SetPosition(occluding_layer_position);

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            occluded_tile_count = 0;
            for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f,
                     gfx::Rect(layer_bounds));
                 iter; ++iter) {
                if (!*iter)
                    continue;
                const Tile* tile = *iter;

                if (prioritized_tiles[tile].is_occluded()) {
                    EXPECT_FALSE(tile->required_for_activation());
                    occluded_tile_count++;
                }
            }
            switch (i) {
            case 0:
                EXPECT_EQ(occluded_tile_count, 5);
                break;
            case 1:
                EXPECT_EQ(occluded_tile_count, 2);
                break;
            default:
                NOTREACHED();
            }
        }

        // Full occlusion.
        layer1->SetPosition(gfx::PointF());
        layer1->NoteLayerPropertyChanged();

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200));
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            occluded_tile_count = 0;
            for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f,
                     gfx::Rect(layer_bounds));
                 iter; ++iter) {
                if (!*iter)
                    continue;
                const Tile* tile = *iter;

                if (prioritized_tiles[tile].is_occluded()) {
                    EXPECT_FALSE(tile->required_for_activation());
                    occluded_tile_count++;
                }
            }
            switch (i) {
            case 0:
                EXPECT_EQ(25, occluded_tile_count);
                break;
            case 1:
                EXPECT_EQ(4, occluded_tile_count);
                break;
            default:
                NOTREACHED();
            }
        }
    }

    TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(500, 500);
        gfx::PointF occluding_layer_position(310.f, 0.f);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->SetViewportSize(viewport_size);

        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ASSERT_TRUE(pending_layer()->CanHaveTilings());

        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 1));
        LayerImpl* layer1 = pending_layer()->test_properties()->children[0];
        layer1->SetBounds(layer_bounds);
        layer1->SetDrawsContent(true);
        layer1->SetContentsOpaque(true);
        layer1->SetPosition(occluding_layer_position);

        pending_layer()->tilings()->RemoveAllTilings();
        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        pending_layer()->AddTiling(low_res_factor)->set_resolution(LOW_RESOLUTION);
        pending_layer()->AddTiling(0.3f)->set_resolution(HIGH_RESOLUTION);
        pending_layer()->AddTiling(0.7f)->set_resolution(HIGH_RESOLUTION);
        pending_layer()->AddTiling(1.0f)->set_resolution(HIGH_RESOLUTION);
        pending_layer()->AddTiling(2.0f)->set_resolution(HIGH_RESOLUTION);

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        // UpdateDrawProperties with the occluding layer.
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        EXPECT_EQ(5u, pending_layer()->num_tilings());

        int occluded_tile_count = 0;
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();

            occluded_tile_count = 0;
            for (size_t j = 0; j < tiles.size(); ++j) {
                if (prioritized_tiles[tiles[j]].is_occluded()) {
                    gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
                        tiles[j]->content_rect(), 1.f / tiles[j]->contents_scale());
                    EXPECT_GE(scaled_content_rect.x(), occluding_layer_position.x());
                    occluded_tile_count++;
                }
            }

            switch (i) {
            case 0:
                EXPECT_EQ(occluded_tile_count, 30);
                break;
            case 1:
                EXPECT_EQ(occluded_tile_count, 5);
                break;
            case 2:
                EXPECT_EQ(occluded_tile_count, 4);
                break;
            case 4:
            case 3:
                EXPECT_EQ(occluded_tile_count, 2);
                break;
            default:
                NOTREACHED();
            }
        }
    }

    TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees)
    {
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(1000, 1000);
        gfx::PointF occluding_layer_position(310.f, 0.f);
        gfx::Rect invalidation_rect(230, 230, 102, 102);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->SetViewportSize(viewport_size);
        SetupPendingTree(active_raster_source);

        // Partially occlude the active layer.
        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 2));
        LayerImpl* layer1 = pending_layer()->test_properties()->children[0];
        layer1->SetBounds(layer_bounds);
        layer1->SetDrawsContent(true);
        layer1->SetContentsOpaque(true);
        layer1->SetPosition(occluding_layer_position);

        ActivateTree();

        for (size_t i = 0; i < active_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f,
                     gfx::Rect(layer_bounds));
                 iter; ++iter) {
                if (!*iter)
                    continue;
                const Tile* tile = *iter;

                gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
                    tile->content_rect(), 1.f / tile->contents_scale());
                // Tiles are occluded on the active tree iff they lie beneath the
                // occluding layer.
                EXPECT_EQ(prioritized_tiles[tile].is_occluded(),
                    scaled_content_rect.x() >= occluding_layer_position.x());
            }
        }

        // Partially invalidate the pending layer.
        SetupPendingTreeWithInvalidation(pending_raster_source, invalidation_rect);

        for (size_t i = 0; i < active_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f,
                     gfx::Rect(layer_bounds));
                 iter; ++iter) {
                if (!*iter)
                    continue;
                const Tile* tile = *iter;
                EXPECT_TRUE(tile);

                // All tiles are unoccluded, because the pending tree has no occlusion.
                EXPECT_FALSE(prioritized_tiles[tile].is_occluded());

                if (tiling->resolution() == LOW_RESOLUTION) {
                    EXPECT_FALSE(active_layer()->GetPendingOrActiveTwinTiling(tiling));
                    continue;
                }

                Tile* twin_tile = active_layer()->GetPendingOrActiveTwinTiling(tiling)->TileAt(
                    iter.i(), iter.j());
                gfx::Rect scaled_content_rect = ScaleToEnclosingRect(
                    tile->content_rect(), 1.f / tile->contents_scale());

                if (scaled_content_rect.Intersects(invalidation_rect)) {
                    // Tiles inside the invalidation rect exist on both trees.
                    EXPECT_TRUE(twin_tile);
                    EXPECT_NE(tile, twin_tile);
                } else {
                    // Tiles outside the invalidation rect only exist on the active tree.
                    EXPECT_FALSE(twin_tile);
                }
            }
        }
    }

    TEST_F(OcclusionTrackingPictureLayerImplTest,
        OccludedTilesConsideredDuringEviction)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(1000, 1000);
        gfx::PointF pending_occluding_layer_position(310.f, 0.f);
        gfx::PointF active_occluding_layer_position(0.f, 310.f);
        gfx::Rect invalidation_rect(230, 230, 152, 152);

        host_impl()->SetViewportSize(viewport_size);
        SetInitialDeviceScaleFactor(2.f);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTreeWithFixedTileSize(active_raster_source, tile_size, Region());

        // Partially occlude the active layer.
        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 2));
        LayerImpl* active_occluding_layer = pending_layer()->test_properties()->children[0];
        active_occluding_layer->SetBounds(layer_bounds);
        active_occluding_layer->SetDrawsContent(true);
        active_occluding_layer->SetContentsOpaque(true);
        active_occluding_layer->SetPosition(active_occluding_layer_position);

        ActivateTree();

        // Partially invalidate the pending layer. Tiles inside the invalidation rect
        // are created.
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
            invalidation_rect);

        // Partially occlude the pending layer in a different way.
        pending_layer()->test_properties()->AddChild(
            LayerImpl::Create(host_impl()->pending_tree(), 3));
        LayerImpl* pending_occluding_layer = pending_layer()->test_properties()->children[0];
        pending_occluding_layer->SetBounds(layer_bounds);
        pending_occluding_layer->SetDrawsContent(true);
        pending_occluding_layer->SetContentsOpaque(true);
        pending_occluding_layer->SetPosition(pending_occluding_layer_position);

        EXPECT_EQ(1u, pending_layer()->num_tilings());
        EXPECT_EQ(2u, active_layer()->num_tilings());

        RebuildPropertyTreesOnPendingTree();
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
        // UpdateDrawProperties with the occluding layer.
        bool update_lcd_text = false;
        host_impl()->pending_tree()->UpdateDrawProperties(update_lcd_text);

        float dest_scale = std::max(active_layer()->MaximumTilingContentsScale(),
            pending_layer()->MaximumTilingContentsScale());
        gfx::Rect dest_layer_bounds = gfx::ScaleToEnclosingRect(gfx::Rect(layer_bounds), dest_scale);
        gfx::Rect dest_invalidation_rect = gfx::ScaleToEnclosingRect(invalidation_rect, dest_scale);

        // The expected number of occluded tiles on each of the 2 tilings for each of
        // the 3 tree priorities.
        size_t expected_occluded_tile_count_on_pending[] = { 4u, 0u };
        size_t expected_occluded_tile_count_on_active[] = { 12u, 3u };
        size_t total_expected_occluded_tile_count_on_trees[] = { 15u, 4u };

        // Verify number of occluded tiles on the pending layer for each tiling.
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            size_t occluded_tile_count_on_pending = 0u;
            for (PictureLayerTiling::CoverageIterator iter(tiling, dest_scale,
                     dest_layer_bounds);
                 iter; ++iter) {
                Tile* tile = *iter;

                if (dest_invalidation_rect.Intersects(iter.geometry_rect()))
                    EXPECT_TRUE(tile);
                else
                    EXPECT_FALSE(tile);

                if (!tile)
                    continue;
                if (prioritized_tiles[tile].is_occluded())
                    occluded_tile_count_on_pending++;
            }
            EXPECT_EQ(expected_occluded_tile_count_on_pending[i],
                occluded_tile_count_on_pending)
                << tiling->contents_scale();
        }

        // Verify number of occluded tiles on the active layer for each tiling.
        for (size_t i = 0; i < active_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i);
            auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

            size_t occluded_tile_count_on_active = 0u;
            for (PictureLayerTiling::CoverageIterator iter(tiling, dest_scale,
                     dest_layer_bounds);
                 iter; ++iter) {
                Tile* tile = *iter;

                if (!tile)
                    continue;
                if (prioritized_tiles[tile].is_occluded())
                    occluded_tile_count_on_active++;
            }
            EXPECT_EQ(expected_occluded_tile_count_on_active[i],
                occluded_tile_count_on_active)
                << i;
        }

        std::vector<Tile*> all_tiles;
        for (size_t i = 0; i < pending_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = pending_layer()->tilings()->tiling_at(i);
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            all_tiles.insert(all_tiles.end(), tiles.begin(), tiles.end());
        }
        for (size_t i = 0; i < active_layer()->num_tilings(); ++i) {
            PictureLayerTiling* tiling = active_layer()->tilings()->tiling_at(i);
            std::vector<Tile*> tiles = tiling->AllTilesForTesting();
            all_tiles.insert(all_tiles.end(), tiles.begin(), tiles.end());
        }

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            all_tiles);

        VerifyEvictionConsidersOcclusion(
            pending_layer(), PENDING_TREE,
            total_expected_occluded_tile_count_on_trees[PENDING_TREE], __LINE__);
        VerifyEvictionConsidersOcclusion(
            active_layer(), ACTIVE_TREE,
            total_expected_occluded_tile_count_on_trees[ACTIVE_TREE], __LINE__);

        // Repeat the tests without valid active tree priorities.
        active_layer()->set_has_valid_tile_priorities(false);
        VerifyEvictionConsidersOcclusion(
            pending_layer(), PENDING_TREE,
            total_expected_occluded_tile_count_on_trees[PENDING_TREE], __LINE__);
        VerifyEvictionConsidersOcclusion(
            active_layer(), ACTIVE_TREE,
            total_expected_occluded_tile_count_on_trees[ACTIVE_TREE], __LINE__);
        active_layer()->set_has_valid_tile_priorities(true);

        // Repeat the tests without valid pending tree priorities.
        pending_layer()->set_has_valid_tile_priorities(false);
        VerifyEvictionConsidersOcclusion(
            active_layer(), ACTIVE_TREE,
            total_expected_occluded_tile_count_on_trees[ACTIVE_TREE], __LINE__);
        VerifyEvictionConsidersOcclusion(
            pending_layer(), PENDING_TREE,
            total_expected_occluded_tile_count_on_trees[PENDING_TREE], __LINE__);
        pending_layer()->set_has_valid_tile_priorities(true);
    }

    TEST_F(PictureLayerImplTest, PendingOrActiveTwinLayer)
    {
        gfx::Size layer_bounds(1000, 1000);

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(raster_source);
        EXPECT_FALSE(pending_layer()->GetPendingOrActiveTwinLayer());

        ActivateTree();
        EXPECT_FALSE(active_layer()->GetPendingOrActiveTwinLayer());

        SetupPendingTree(raster_source);
        EXPECT_TRUE(pending_layer()->GetPendingOrActiveTwinLayer());
        EXPECT_TRUE(active_layer()->GetPendingOrActiveTwinLayer());
        EXPECT_EQ(pending_layer(), active_layer()->GetPendingOrActiveTwinLayer());
        EXPECT_EQ(active_layer(), pending_layer()->GetPendingOrActiveTwinLayer());

        ActivateTree();
        EXPECT_FALSE(active_layer()->GetPendingOrActiveTwinLayer());

        // Make an empty pending tree.
        host_impl()->CreatePendingTree();
        host_impl()->pending_tree()->DetachLayers();
        EXPECT_FALSE(active_layer()->GetPendingOrActiveTwinLayer());
    }

    void GetClientDataAndUpdateInvalidation(RecordingSource* recording_source,
        FakeContentLayerClient* client,
        Region invalidation,
        gfx::Size layer_bounds)
    {
        gfx::Rect new_recorded_viewport = client->PaintableRegion();
        scoped_refptr<DisplayItemList> display_list = client->PaintContentsToDisplayList(
            ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
        size_t painter_reported_memory_usage = client->GetApproximateUnsharedMemoryUsage();

        recording_source->UpdateAndExpandInvalidation(&invalidation, layer_bounds,
            new_recorded_viewport);
        recording_source->UpdateDisplayItemList(display_list,
            painter_reported_memory_usage);
    }

    void PictureLayerImplTest::TestQuadsForSolidColor(bool test_for_solid)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);
        gfx::Rect layer_rect(layer_bounds);

        FakeContentLayerClient client;
        client.set_bounds(layer_bounds);
        scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
        FakeLayerTreeHostClient host_client;
        TestTaskGraphRunner task_graph_runner;
        auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
        std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
            &host_client, &task_graph_runner, animation_host.get());
        host->SetRootLayer(layer);
        RecordingSource* recording_source = layer->GetRecordingSourceForTesting();

        client.set_fill_with_nonsolid_color(!test_for_solid);

        Region invalidation(layer_rect);

        GetClientDataAndUpdateInvalidation(recording_source, &client, invalidation,
            layer_bounds);

        scoped_refptr<RasterSource> pending_raster_source = recording_source->CreateRasterSource(true);

        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());
        ActivateTree();

        if (test_for_solid) {
            EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
        } else {
            ASSERT_TRUE(active_layer()->tilings());
            ASSERT_GT(active_layer()->tilings()->num_tilings(), 0u);
            std::vector<Tile*> tiles = active_layer()->tilings()->tiling_at(0)->AllTilesForTesting();
            EXPECT_FALSE(tiles.empty());
            host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
        }

        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer()->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer()->AppendQuads(render_pass.get(), &data);
        active_layer()->DidDraw(nullptr);

        DrawQuad::Material expected = test_for_solid
            ? DrawQuad::Material::SOLID_COLOR
            : DrawQuad::Material::TILED_CONTENT;
        EXPECT_EQ(expected, render_pass->quad_list.front()->material);
    }

    TEST_F(PictureLayerImplTest, DrawSolidQuads)
    {
        TestQuadsForSolidColor(true);
    }

    TEST_F(PictureLayerImplTest, DrawNonSolidQuads)
    {
        TestQuadsForSolidColor(false);
    }

    TEST_F(PictureLayerImplTest, NonSolidToSolidNoTilings)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(200, 200);
        gfx::Rect layer_rect(layer_bounds);

        FakeContentLayerClient client;
        client.set_bounds(layer_bounds);
        scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
        FakeLayerTreeHostClient host_client;
        TestTaskGraphRunner task_graph_runner;
        auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
        std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
            &host_client, &task_graph_runner, animation_host.get());
        host->SetRootLayer(layer);
        RecordingSource* recording_source = layer->GetRecordingSourceForTesting();

        client.set_fill_with_nonsolid_color(true);

        recording_source->SetNeedsDisplayRect(layer_rect);
        Region invalidation1;

        GetClientDataAndUpdateInvalidation(recording_source, &client, invalidation1,
            layer_bounds);

        scoped_refptr<RasterSource> raster_source1 = recording_source->CreateRasterSource(true);

        SetupPendingTree(raster_source1);
        ActivateTree();
        bool update_lcd_text = false;
        host_impl()->active_tree()->UpdateDrawProperties(update_lcd_text);

        // We've started with a solid layer that contains some tilings.
        ASSERT_TRUE(active_layer()->tilings());
        EXPECT_NE(0u, active_layer()->tilings()->num_tilings());

        client.set_fill_with_nonsolid_color(false);

        recording_source->SetNeedsDisplayRect(layer_rect);
        Region invalidation2;

        GetClientDataAndUpdateInvalidation(recording_source, &client, invalidation2,
            layer_bounds);

        scoped_refptr<RasterSource> raster_source2 = recording_source->CreateRasterSource(true);

        SetupPendingTree(raster_source2);
        ActivateTree();

        // We've switched to a solid color, so we should end up with no tilings.
        ASSERT_TRUE(active_layer()->tilings());
        EXPECT_EQ(0u, active_layer()->tilings()->num_tilings());
    }

    TEST_F(PictureLayerImplTest, ChangeInViewportAllowsTilingUpdates)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size layer_bounds(400, 4000);
        SetupDefaultTrees(layer_bounds);

        Region invalidation;
        gfx::Rect viewport = gfx::Rect(0, 0, 100, 100);
        gfx::Transform transform;

        host_impl()->SetRequiresHighResToDraw();

        // Update tiles.
        pending_layer()->draw_properties().visible_layer_rect = viewport;
        pending_layer()->draw_properties().screen_space_transform = transform;
        SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();

        // Ensure we can't activate.
        EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToActivate());

        // Now in the same frame, move the viewport (this can happen during
        // animation).
        viewport = gfx::Rect(0, 2000, 100, 100);

        // Update tiles.
        pending_layer()->draw_properties().visible_layer_rect = viewport;
        pending_layer()->draw_properties().screen_space_transform = transform;
        SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
            false);
        pending_layer()->HighResTiling()->UpdateAllRequiredStateForTesting();

        // Make sure all viewport tiles (viewport from the tiling) are ready to draw.
        std::vector<Tile*> tiles;
        for (PictureLayerTiling::CoverageIterator iter(
                 pending_layer()->HighResTiling(), 1.f,
                 pending_layer()->HighResTiling()->GetCurrentVisibleRectForTesting());
             iter; ++iter) {
            if (*iter)
                tiles.push_back(*iter);
        }
        for (PictureLayerTiling::CoverageIterator iter(
                 active_layer()->HighResTiling(), 1.f,
                 active_layer()->HighResTiling()->GetCurrentVisibleRectForTesting());
             iter; ++iter) {
            if (*iter)
                tiles.push_back(*iter);
        }

        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(tiles);

        // Ensure we can activate.
        EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToActivate());
    }

    TEST_F(PictureLayerImplTest, CloneMissingRecordings)
    {
        gfx::Size tile_size(100, 100);
        gfx::Size layer_bounds(400, 400);

        scoped_refptr<FakeRasterSource> filled_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        scoped_refptr<FakeRasterSource> partial_raster_source = FakeRasterSource::CreatePartiallyFilled(layer_bounds,
            gfx::Rect(100, 100, 300, 300));

        SetupPendingTreeWithFixedTileSize(filled_raster_source, tile_size, Region());
        ActivateTree();

        PictureLayerTiling* pending_tiling = old_pending_layer()->HighResTiling();
        PictureLayerTiling* active_tiling = active_layer()->HighResTiling();

        // We should have all tiles on active, and none on pending.
        EXPECT_EQ(0u, pending_tiling->AllTilesForTesting().size());
        EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size());

        // Now put a partially-recorded raster source on the pending tree (and
        // invalidate everything, since the main thread recording will invalidate
        // dropped recordings). This will cause us to be missing some tiles.
        SetupPendingTreeWithFixedTileSize(partial_raster_source, tile_size,
            Region(gfx::Rect(layer_bounds)));
        EXPECT_EQ(3u * 3u, pending_tiling->AllTilesForTesting().size());
        EXPECT_FALSE(pending_tiling->TileAt(0, 0));
        EXPECT_FALSE(pending_tiling->TileAt(1, 1));
        EXPECT_TRUE(pending_tiling->TileAt(2, 2));

        // Active is not affected yet.
        EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size());

        // Activate the tree. The same tiles go missing on the active tree.
        ActivateTree();
        EXPECT_EQ(3u * 3u, active_tiling->AllTilesForTesting().size());
        EXPECT_FALSE(active_tiling->TileAt(0, 0));
        EXPECT_FALSE(active_tiling->TileAt(1, 1));
        EXPECT_TRUE(active_tiling->TileAt(2, 2));

        // Now put a full recording on the pending tree again. We'll get all our tiles
        // back.
        SetupPendingTreeWithFixedTileSize(filled_raster_source, tile_size,
            Region(gfx::Rect(layer_bounds)));
        EXPECT_EQ(5u * 5u, pending_tiling->AllTilesForTesting().size());
        Tile::Id tile00 = pending_tiling->TileAt(0, 0)->id();
        Tile::Id tile11 = pending_tiling->TileAt(1, 1)->id();
        Tile::Id tile22 = pending_tiling->TileAt(2, 2)->id();

        // Active is not affected yet.
        EXPECT_EQ(3u * 3u, active_tiling->AllTilesForTesting().size());

        // Activate the tree. The tiles are moved to the active tree.
        ActivateTree();
        EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size());
        EXPECT_EQ(tile00, active_tiling->TileAt(0, 0)->id());
        EXPECT_EQ(tile11, active_tiling->TileAt(1, 1)->id());
        EXPECT_EQ(tile22, active_tiling->TileAt(2, 2)->id());
    }

    TEST_F(PictureLayerImplTest, ScrollPastLiveTilesRectAndBack)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(100, 100);
        gfx::Size viewport_size(100, 100);

        host_impl()->SetViewportSize(viewport_size);
        SetInitialDeviceScaleFactor(1.f);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        scoped_refptr<FakeRasterSource> active_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        SetupPendingTreeWithFixedTileSize(active_raster_source, tile_size, Region());

        ActivateTree();
        EXPECT_TRUE(active_layer()->HighResTiling()->has_tiles());

        host_impl()->SetExternalTilePriorityConstraints(gfx::Rect(0, 5000, 100, 100),
            gfx::Transform());

        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
            gfx::Rect());

        EXPECT_FALSE(pending_layer()->HighResTiling()->has_tiles());
        EXPECT_TRUE(pending_layer()->HighResTiling()->live_tiles_rect().IsEmpty());
        ActivateTree();
        EXPECT_FALSE(active_layer()->HighResTiling()->has_tiles());
        EXPECT_TRUE(active_layer()->HighResTiling()->live_tiles_rect().IsEmpty());

        host_impl()->SetExternalTilePriorityConstraints(gfx::Rect(0, 110, 100, 100),
            gfx::Transform());

        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size,
            gfx::Rect());

        EXPECT_FALSE(pending_layer()->HighResTiling()->has_tiles());
        EXPECT_FALSE(pending_layer()->HighResTiling()->live_tiles_rect().IsEmpty());
        ActivateTree();
        EXPECT_TRUE(active_layer()->HighResTiling()->has_tiles());
        EXPECT_FALSE(active_layer()->HighResTiling()->live_tiles_rect().IsEmpty());
    }

    TEST_F(PictureLayerImplTest, ScrollPropagatesToPending)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size layer_bounds(1000, 1000);
        gfx::Size viewport_size(100, 100);

        host_impl()->SetViewportSize(viewport_size);
        SetInitialDeviceScaleFactor(1.f);

        SetupDefaultTrees(layer_bounds);

        active_layer()->SetCurrentScrollOffset(gfx::ScrollOffset(0.0, 50.0));
        host_impl()->active_tree()->UpdateDrawProperties(false);
        EXPECT_EQ("0,50 100x100", active_layer()->HighResTiling()->GetCurrentVisibleRectForTesting().ToString());

        EXPECT_EQ("0,0 100x100", pending_layer()->HighResTiling()->GetCurrentVisibleRectForTesting().ToString());
        host_impl()->pending_tree()->UpdateDrawProperties(false);
        EXPECT_EQ("0,50 100x100", pending_layer()->HighResTiling()->GetCurrentVisibleRectForTesting().ToString());
    }

    TEST_F(PictureLayerImplTest, UpdateLCDInvalidatesPendingTree)
    {
        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        gfx::Size tile_size(102, 102);
        gfx::Size layer_bounds(100, 100);
        gfx::Size viewport_size(100, 100);

        host_impl()->SetViewportSize(viewport_size);
        SetInitialDeviceScaleFactor(1.f);

        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilledLCD(layer_bounds);
        SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region());

        EXPECT_TRUE(pending_layer()->RasterSourceUsesLCDText());
        EXPECT_TRUE(pending_layer()->HighResTiling()->has_tiles());
        std::vector<Tile*> tiles = pending_layer()->HighResTiling()->AllTilesForTesting();
        auto prioritized_tiles = pending_layer()
                                     ->HighResTiling()
                                     ->UpdateAndGetAllPrioritizedTilesForTesting();

        for (Tile* tile : tiles)
            EXPECT_EQ(pending_layer()->raster_source(),
                prioritized_tiles[tile].raster_source());

        pending_layer()->SetContentsOpaque(false);
        pending_layer()->UpdateCanUseLCDTextAfterCommit();

        EXPECT_FALSE(pending_layer()->RasterSourceUsesLCDText());
        EXPECT_NE(pending_raster_source.get(), pending_layer()->raster_source());
        EXPECT_TRUE(pending_layer()->HighResTiling()->has_tiles());
        tiles = pending_layer()->HighResTiling()->AllTilesForTesting();
        prioritized_tiles = pending_layer()
                                ->HighResTiling()
                                ->UpdateAndGetAllPrioritizedTilesForTesting();
        for (Tile* tile : tiles)
            EXPECT_EQ(pending_layer()->raster_source(),
                prioritized_tiles[tile].raster_source());
    }

    TEST_F(PictureLayerImplTest, TilingAllTilesDone)
    {
        gfx::Size tile_size = host_impl()->settings().default_tile_size;
        size_t tile_mem = 4 * tile_size.width() * tile_size.height();
        gfx::Size layer_bounds(1000, 1000);

        // Create tiles.
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        SetupPendingTree(pending_raster_source);
        pending_layer()->SetBounds(layer_bounds);
        ActivateTree();
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            active_layer()->HighResTiling()->AllTilesForTesting());
        host_impl()->SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);

        EXPECT_FALSE(active_layer()->HighResTiling()->all_tiles_done());

        {
            // Set a memory policy that will fit all tiles.
            size_t max_tiles = 16;
            size_t memory_limit = max_tiles * tile_mem;
            ManagedMemoryPolicy policy(memory_limit,
                gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
                max_tiles);
            host_impl()->SetMemoryPolicy(policy);
            host_impl()->PrepareTiles();

            EXPECT_TRUE(active_layer()->HighResTiling()->all_tiles_done());
        }

        {
            // Set a memory policy that will cause tile eviction.
            size_t max_tiles = 1;
            size_t memory_limit = max_tiles * tile_mem;
            ManagedMemoryPolicy policy(memory_limit,
                gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
                max_tiles);
            host_impl()->SetMemoryPolicy(policy);
            host_impl()->PrepareTiles();

            EXPECT_FALSE(active_layer()->HighResTiling()->all_tiles_done());
        }
    }

    class TileSizeTest : public PictureLayerImplTest {
    public:
        LayerTreeSettings CreateSettings() override
        {
            LayerTreeSettings settings = PictureLayerImplTest::CreateSettings();
            settings.default_tile_size = gfx::Size(100, 100);
            settings.max_untiled_layer_size = gfx::Size(200, 200);
            return settings;
        }
    };

    TEST_F(TileSizeTest, TileSizes)
    {
        host_impl()->CreatePendingTree();

        LayerTreeImpl* pending_tree = host_impl()->pending_tree();
        std::unique_ptr<FakePictureLayerImpl> layer = FakePictureLayerImpl::Create(pending_tree, layer_id());

        host_impl()->SetViewportSize(gfx::Size(1000, 1000));
        gfx::Size result;

        host_impl()->SetContentIsSuitableForGpuRasterization(true);
        host_impl()->SetHasGpuRasterizationTrigger(false);
        host_impl()->CommitComplete();
        EXPECT_EQ(host_impl()->gpu_rasterization_status(),
            GpuRasterizationStatus::OFF_VIEWPORT);

        // Default tile-size for large layers.
        result = layer->CalculateTileSize(gfx::Size(10000, 10000));
        EXPECT_EQ(result.width(), 100);
        EXPECT_EQ(result.height(), 100);
        // Don't tile and round-up, when under max_untiled_layer_size.
        result = layer->CalculateTileSize(gfx::Size(42, 42));
        EXPECT_EQ(result.width(), 64);
        EXPECT_EQ(result.height(), 64);
        result = layer->CalculateTileSize(gfx::Size(191, 191));
        EXPECT_EQ(result.width(), 192);
        EXPECT_EQ(result.height(), 192);
        result = layer->CalculateTileSize(gfx::Size(199, 199));
        EXPECT_EQ(result.width(), 200);
        EXPECT_EQ(result.height(), 200);

        // Gpu-rasterization uses 25% viewport-height tiles.
        // The +2's below are for border texels.
        host_impl()->SetHasGpuRasterizationTrigger(true);
        host_impl()->CommitComplete();
        EXPECT_EQ(host_impl()->gpu_rasterization_status(),
            GpuRasterizationStatus::ON);
        host_impl()->SetViewportSize(gfx::Size(2000, 2000));

        layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
        result = layer->CalculateTileSize(gfx::Size(10000, 10000));
        EXPECT_EQ(result.width(),
            MathUtil::UncheckedRoundUp(
                2000 + 2 * PictureLayerTiling::kBorderTexels, 32));
        EXPECT_EQ(result.height(), 512); // 500 + 2, 32-byte aligned.

        // Clamp and round-up, when smaller than viewport.
        // Tile-height doubles to 50% when width shrinks to <= 50%.
        host_impl()->SetViewportSize(gfx::Size(1000, 1000));
        layer->set_gpu_raster_max_texture_size(host_impl()->device_viewport_size());
        result = layer->CalculateTileSize(gfx::Size(447, 10000));
        EXPECT_EQ(result.width(), 448);
        EXPECT_EQ(result.height(), 512); // 500 + 2, 32-byte aliged.

        // Largest layer is 50% of viewport width (rounded up), and
        // 50% of viewport in height.
        result = layer->CalculateTileSize(gfx::Size(447, 400));
        EXPECT_EQ(result.width(), 448);
        EXPECT_EQ(result.height(), 448);
        result = layer->CalculateTileSize(gfx::Size(500, 499));
        EXPECT_EQ(result.width(), 512);
        EXPECT_EQ(result.height(), 512); // 500 + 2, 32-byte aligned.
    }

    TEST_F(NoLowResPictureLayerImplTest, LowResWasHighResCollision)
    {
        gfx::Size layer_bounds(1300, 1900);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;
        SetupDefaultTrees(layer_bounds);
        ResetTilingsAndRasterScales();

        float page_scale = 2.f;
        SetContentsScaleOnBothLayers(page_scale, 1.0f, page_scale, 1.0f, 0.f, false);
        EXPECT_BOTH_EQ(num_tilings(), 1u);
        EXPECT_BOTH_EQ(tilings()->tiling_at(0)->contents_scale(), page_scale);

        host_impl()->PinchGestureBegin();

        // Zoom out to exactly the low res factor so that the previous high res
        // would be equal to the current low res (if it were possible to have one).
        float zoomed = page_scale / low_res_factor;
        SetContentsScaleOnBothLayers(zoomed, 1.0f, zoomed, 1.0f, 0.f, false);
        EXPECT_EQ(1u, pending_layer()->num_tilings());
        EXPECT_EQ(zoomed, pending_layer()->tilings()->tiling_at(0)->contents_scale());
    }

    TEST_F(PictureLayerImplTest, HighResWasLowResCollision)
    {
        gfx::Size layer_bounds(1300, 1900);

        float low_res_factor = host_impl()->settings().low_res_contents_scale_factor;

        SetupDefaultTrees(layer_bounds);
        ResetTilingsAndRasterScales();

        float page_scale = 4.f;
        float low_res = page_scale * low_res_factor;
        float extra_low_res = low_res * low_res_factor;
        SetupDrawPropertiesAndUpdateTiles(active_layer(), page_scale, 1.0f,
            page_scale, 1.0f, 0.f, false);
        EXPECT_EQ(2u, active_layer()->tilings()->num_tilings());
        EXPECT_EQ(page_scale,
            active_layer()->tilings()->tiling_at(0)->contents_scale());
        EXPECT_EQ(low_res, active_layer()->tilings()->tiling_at(1)->contents_scale());

        // Grab a current low res tile.
        PictureLayerTiling* old_low_res_tiling = active_layer()->tilings()->tiling_at(1);
        Tile::Id old_low_res_tile_id = active_layer()->tilings()->tiling_at(1)->TileAt(0, 0)->id();

        // The tiling knows it has low res content.
        EXPECT_TRUE(active_layer()
                        ->tilings()
                        ->tiling_at(1)
                        ->may_contain_low_resolution_tiles());

        host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));

        // Zoom in to exactly the low res factor so that the previous low res
        // would be equal to the current high res.
        SetupDrawPropertiesAndUpdateTiles(active_layer(), low_res, 1.0f, low_res,
            1.0f, 0.f, false);
        // 3 tilings. The old high res, the new high res (old low res) and the new low
        // res.
        EXPECT_EQ(3u, active_layer()->num_tilings());

        PictureLayerTilingSet* tilings = active_layer()->tilings();
        EXPECT_EQ(page_scale, tilings->tiling_at(0)->contents_scale());
        EXPECT_EQ(low_res, tilings->tiling_at(1)->contents_scale());
        EXPECT_EQ(extra_low_res, tilings->tiling_at(2)->contents_scale());

        EXPECT_EQ(NON_IDEAL_RESOLUTION, tilings->tiling_at(0)->resolution());
        EXPECT_EQ(HIGH_RESOLUTION, tilings->tiling_at(1)->resolution());
        EXPECT_EQ(LOW_RESOLUTION, tilings->tiling_at(2)->resolution());

        // The old low res tile was destroyed and replaced.
        EXPECT_EQ(old_low_res_tiling, tilings->tiling_at(1));
        EXPECT_NE(old_low_res_tile_id, tilings->tiling_at(1)->TileAt(0, 0)->id());
        EXPECT_TRUE(tilings->tiling_at(1)->TileAt(0, 0));

        // New high res tiling.
        EXPECT_FALSE(tilings->tiling_at(0)->may_contain_low_resolution_tiles());
        // New low res tiling.
        EXPECT_TRUE(tilings->tiling_at(2)->may_contain_low_resolution_tiles());

        // This tiling will be high res now, it won't contain low res content since it
        // was all destroyed.
        EXPECT_FALSE(tilings->tiling_at(1)->may_contain_low_resolution_tiles());
    }

    TEST_F(PictureLayerImplTest, CompositedImageCalculateContentsScale)
    {
        gfx::Size layer_bounds(400, 400);
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->CreatePendingTree();
        LayerTreeImpl* pending_tree = host_impl()->pending_tree();

        std::unique_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id(),
            pending_raster_source);
        pending_layer->set_is_directly_composited_image(true);
        pending_layer->SetDrawsContent(true);
        FakePictureLayerImpl* pending_layer_ptr = pending_layer.get();
        pending_tree->SetRootLayerForTesting(std::move(pending_layer));
        pending_tree->BuildLayerListAndPropertyTreesForTesting();

        SetupDrawPropertiesAndUpdateTiles(pending_layer_ptr, 2.f, 3.f, 4.f, 1.f, 1.f,
            false);
        EXPECT_FLOAT_EQ(1.f, pending_layer_ptr->MaximumTilingContentsScale());
    }

    TEST_F(PictureLayerImplTest, CompositedImageIgnoreIdealContentsScale)
    {
        gfx::Size layer_bounds(400, 400);
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->SetViewportSize(layer_bounds);
        host_impl()->CreatePendingTree();
        LayerTreeImpl* pending_tree = host_impl()->pending_tree();

        std::unique_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id(),
            pending_raster_source);
        pending_layer->set_is_directly_composited_image(true);
        pending_layer->SetDrawsContent(true);
        FakePictureLayerImpl* pending_layer_ptr = pending_layer.get();
        pending_tree->SetRootLayerForTesting(std::move(pending_layer));
        pending_tree->BuildLayerListAndPropertyTreesForTesting();

        // Set PictureLayerImpl::ideal_contents_scale_ to 2.f.
        const float suggested_ideal_contents_scale = 2.f;
        const float device_scale_factor = 3.f;
        const float page_scale_factor = 4.f;
        const float animation_contents_scale = 1.f;
        const bool animating_transform_to_screen = false;
        SetupDrawPropertiesAndUpdateTiles(
            pending_layer_ptr, suggested_ideal_contents_scale, device_scale_factor,
            page_scale_factor, animation_contents_scale, animation_contents_scale,
            animating_transform_to_screen);
        EXPECT_EQ(1.f, pending_layer_ptr->tilings()->tiling_at(0)->contents_scale());

        // Push to active layer.
        host_impl()->ActivateSyncTree();

        FakePictureLayerImpl* active_layer = static_cast<FakePictureLayerImpl*>(
            host_impl()->active_tree()->root_layer_for_testing());
        SetupDrawPropertiesAndUpdateTiles(
            active_layer, suggested_ideal_contents_scale, device_scale_factor,
            page_scale_factor, animation_contents_scale, animation_contents_scale,
            animating_transform_to_screen);
        EXPECT_EQ(1.f, active_layer->tilings()->tiling_at(0)->contents_scale());
        active_layer->set_visible_layer_rect(gfx::Rect(layer_bounds));

        // Create resources for the tiles.
        host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
            active_layer->tilings()->tiling_at(0)->AllTilesForTesting());

        // Draw.
        std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
        AppendQuadsData data;
        active_layer->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
        active_layer->AppendQuads(render_pass.get(), &data);
        active_layer->DidDraw(nullptr);

        ASSERT_FALSE(render_pass->quad_list.empty());
        EXPECT_EQ(DrawQuad::TILED_CONTENT, render_pass->quad_list.front()->material);

        // Tiles are ready at correct scale, so should not set had_incomplete_tile.
        EXPECT_EQ(0, data.num_incomplete_tiles);
    }

    TEST_F(PictureLayerImplTest, CompositedImageRasterScaleChanges)
    {
        gfx::Size layer_bounds(400, 400);
        scoped_refptr<FakeRasterSource> pending_raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        host_impl()->CreatePendingTree();
        LayerTreeImpl* pending_tree = host_impl()->pending_tree();

        std::unique_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id(),
            pending_raster_source);
        pending_layer->set_is_directly_composited_image(true);
        pending_layer->SetDrawsContent(true);
        FakePictureLayerImpl* pending_layer_ptr = pending_layer.get();
        pending_tree->SetRootLayerForTesting(std::move(pending_layer));
        pending_tree->BuildLayerListAndPropertyTreesForTesting();

        float expected_contents_scale = 0.25f;
        for (int i = 1; i < 30; ++i) {
            float ideal_contents_scale = 0.1f * i - 1e-6;
            switch (i) {
            // Scale 0.3.
            case 3:
                expected_contents_scale = 0.5f;
                break;
            // Scale 0.6.
            case 6:
                expected_contents_scale = 1.f;
                break;
            }
            SetupDrawPropertiesAndUpdateTiles(pending_layer_ptr, ideal_contents_scale,
                1.f, 1.f, 1.f, 1.f, false);
            EXPECT_FLOAT_EQ(expected_contents_scale,
                pending_layer_ptr->picture_layer_tiling_set()
                    ->FindTilingWithResolution(HIGH_RESOLUTION)
                    ->contents_scale())
                << "ideal_contents_scale: " << ideal_contents_scale;
        }

        expected_contents_scale = 1.f;
        for (int i = 30; i >= 1; --i) {
            float ideal_contents_scale = 0.1f * i - 1e-6;
            switch (i) {
            // Scale 0.2.
            case 2:
                expected_contents_scale = 0.5f;
                break;
            // Scale 0.1.
            case 1:
                expected_contents_scale = 0.25f;
                break;
            }
            SetupDrawPropertiesAndUpdateTiles(pending_layer_ptr, ideal_contents_scale,
                1.f, 1.f, 1.f, 1.f, false);
            EXPECT_FLOAT_EQ(expected_contents_scale,
                pending_layer_ptr->picture_layer_tiling_set()
                    ->FindTilingWithResolution(HIGH_RESOLUTION)
                    ->contents_scale())
                << "ideal_contents_scale: " << ideal_contents_scale;
        }
    }

} // namespace
} // namespace cc
